Skip to main content

No Domain Logic Into the Infrastructure

Context

Microservices are in use or are planned to be adopted. It is still unclear or it is revisited where domain, resilience, and security logic is located in the system - in microservices, in infrastructure components like API gatways or messaging systems, or in side-cars.

Problem

  • Programming logic that is distributed all over the system - not only the microservices, but also the infrastructure - results in the following effects:
    • Tracing down defects to their root cause is very time consuming since monitoring might not be available on some of the infrastructure components.
    • More and more logic is moved from the microservices themselves to the integration layer or infrastructure. An indicator might be a newly introduced organizational unit was introduced to manage the rising complexity of the integration layer or infrastructure components. The integration layer or infrastructure components become the bottleneck with the increasing amount of business logic to implement, slowing down the innovation speed of the whole system.

Solution

Don't move business logic into the integration layer or infrastructure components. Only generic behavior applying for the whole system is suited to be moved out of the microservice.

This recommendation is often referenced as the "smart endpoints, dumb pipes" principle and emerged as of the learnings from SOA: avoid a central place of business logic, the ESB.

In an microservice-based architecture we have multiple typical places where business logic can be located:

  • Deployment platform (e.g. Kubernetes)
  • Standalone infrastructure component (e.g. API gateway, message broker)
  • Sidecar processes attached to the microservice instances (e.g. service mesh)
  • Microservice itself (e.g. as explicit code)

Everything requiring domain knowledge should be kept within the microservice itself. Business logic should be explicit as code. This includes domain-motivated alternatives, for example the reaction on timeouts or on failed retries. This approach keeps the business logic consistently in one place - the microservices themselves - and guarantees a consistent support of logging and tracing formats that infrastructure components might not support.

Very generic behavior used through the whole system can be moved to the service mesh which often can act as a rule engine. This decision should be part of the global architecture. Candidates are the detection (but not the reaction) of timeouts, doing a fix number of default retries on omission failures (but not the reaction on the last failed retry because domain alternatives are required).

Generic behavior that should fail fast can be further moved away from the microservice to infrastructure components as the API gateway. A base security can be handled there as well as the protection of the whole system against DoS attacks. Fine-granular user authorization should happen close to the microservice, either in the microservice itself or in the service mesh.

Maturity

Proposed, requires evaluation.

Sources of Evidence

L4:

  • Centralization of the model => requires to put all logic into one place (ESB)
    • routing and data transformation
  • Smart endpoint and dumb network
    • could be a reference to unix model
    • but more referencing the ESB
    • Personal experience: no success with big central ESB
      • all logic into one place (ESB)
    • Reference to Jim Weber's talk n QCon "Does My Bus Look Big in This?"
      • idea of spaghetti box: ESB is panacea for all your ills
      • makes diagrams look nice: one box in middle and all lines are straight
      • but lines are still there, just in the middle of a spaghetti box
      • => [interpretation] doesn't solve the problem

L6:

  • Smart endpoints and dumb pipes
    • keep domain logic internal, in the "endpoints" / services
    • communication medium only to exchange bare messages

L7:

  • comparison SOA vs. microservices
    • principle "smart endpoints and dumb pipes" for microservices and as best practice for SOA
  • different microservice definitions
    • Lewis & Fowler, Newman: both have "smart endpoints and dumb pipes" principle
  • ESB too heavyweight, inflexible, unmanageable
    • message routing and transformation patterns still has to be done somewhere
    • by other patterns as API gateway
    • Question arises: where? API gateway? transformations within first-class service?

L8:

  • first generation of services
    • retry and fallbacks directly in service source code

L22:

  • the bigger a system landscape, the bigger the problem to place business logic into infrastructure / service bus
    • may become bottleneck not governed by a service contract
  • recommendation: place all business intelligence at endpoints
    • even message transformations
    • => service design becomes distributed multilateral approach => scale architecture
  • principle "no intelligence in the ESB" existed before microservices, best practice from SOA

L23:

  • data flows through smart endpoints processing incoming information

L34:

  • prefer simple routing mechanisms without global governance in SOA
  • service responsible for business process management and for interaction with other services
    • no centralized integration via ESB
  • business processes embedded into microservice, not logic in integration
  • microservices sacrifice centralized view on business processes (or generally knowledge)
    • now distributed and hidden across services

L46:

  • concept smart endpoints and dumb pipes is reminiscent of early days of EAI
  • Service model for two speed architecture
    • Entity services: handle persistent data and manage all associated functions (storing, receiving, locking, transactions) => more or less a CRUD service
    • Business service: stateless, directly implements business service capability => provides business value
      • coarser-grained than entity services
      • encapsulate data and logic to deliver business result
      • may consume entity service or business services
    • Technical services: support to business functions, not directly delivering business outcomies
      • utility services: document storage, mailing,...
      • technical utility services: logging, handling technical exceptions
      • linked to form composite business services (service assembly or process orchestration)
    • Business process service
      • stateful service for whole or fragment of one of organization's business process
      • may consume other business process services, business services, entity services, technical services
      • typically implemented on a BPM platform
    • Backend for frontend service
      • provision a particular frontend requirement
      • composed service using business, entity, technical services
      • may be regarded as specialized form of business service built for a particular frontend purpose

L47:

  • Experience report
  • Removed ESB since too big integration method for smaller customers
    • only ministries and large regional council (many more IT resources) were a good fit for an ESB
  • Not everything should run over ESB
    • Knowledge for Enterprise Integration Patterns and its Apache Camel implementation is sparse
  • Alternative: Business Process Management engine => was not adapted to their context
    • automated orchestration routes is too complex for mid-sized applications
    • too expensive to just do routing with BPNM engine
    • risk of introducing coupling
  • Best solution: webhook-based integration
    • best low coupling to complexity ratio

L53:

  • Context: Microservices for IoT (use microservices practices in IoT)
  • subsystem made of API gateway and associated microservices
    • gateway translates protocols
    • gateway does message transformations
    • gateway can instantiate message calls to other gateways
    • => [interpretation] business logic into gateway
  • API gateway to support QoS policies
    • limit number of calls, bytes per second
    • prevent DoS attacks
    • access control policies
    • circuit breaking

L54:

  • Microservices eliminate the ESB
  • Maintain dumb pipes to communicate with, move intelligence to endpoints
    • enhances decoupling property between services

LN41:

  • microservices distribute all logic into smart endpoints and adopt light API gateway for managing services
  • instead of heavier and more sophisticated ESB

LN43:

  • Agreed cibsebszs that complexity should within services instead of messaging pipes

Interview B:

  • Candidates to move to infrastructure
    • Security, access control
    • resilience patterns (domain alternative, retry, timeout, bulkhead)
  • Possible locations of business logic
    • service itself
    • gateway
    • service mesh
    • Kubernetes cluster
  • Very hard decision to make (what is macro, what micro architecture?)
  • Recommendation:
    • everything regarding domain decision (e.g. domain alternatives) into the service itself
    • everything fail-fast: gateway
    • everything in between into service mesh
    • Security:
      • base security, DoS prevention at gateway
      • fine-granular security in service mesh
    • Fault tolerance
      • simple retry is not really domain knowledge
      • domain alternative is domain knowledge => close to service (service itself or mesh)
  • Service mesh
    • new hype => huge discussion about what should be located where
    • often have rule engines
    • can support domain alternatives
      • then business logic distributed to services and mesh
      • alternative: saga service doing the coordination
        • can be mini workflow engine (lightweight solution)
  • Recommendation:
    • business logic should be explicit
    • business logic should not be distributed over infrastructure and code, but be kept together
      • otherwise hard to trace down defects
      • infrastructure often does not support tracing

Interview C:

  • Where to implement security?
    • Facade?
    • In each service?
    • Is there a central token service?
  • Competing complexities (tradeoff): put the complexity into the business logic of one application/microservice vs put it into the communication (distribution)
    • a good mix is necessary
    • some complexity is inherent by the domain that we cannot simplify
    • Good cut necessary to get that right
  • Mistake to put almost no logic into the microservices (and thus no complexity)
    • => logic shifts into communication
    • huge data transfer objects with schemata noone understands anymore
    • different APIs, different comm protocols, different progamming languages
      • loose track of how everything works together
  • Also for understanding what is happening in the system you need logs
    • => [interpretation] that can be done best by having the business logic not in the communication

Interview D:

  • "Smart endpoints and dumb pipes" principle
    • interesting since emerging API management solutions contradicting this
    • ESB through the back door together with service meshes
  • What can be solved by infrastructure?
    • handle omission failures: retry, recognizing a timeout => can be done in service mesh
    • reaction on timeout requires domain alternative => needs to be decided individually => not into service mesh
  • Recommendation:
    • Only generic reactions, pipeline needs to stay dumb
    • => if reaction is domain knowledge agnostic
    • Example: always to a retry, recognizing a timeout
      • but not reaction on timeout, reaction on failed retry since requires domain knowledge
    • Danger otherwise
      • will become a bottleneck
      • who is responsible for the shared infrastructure, and the business logic in it?
        • => don't know, need extra unit for it
        • this unit will be the bottleneck determining the whole reaction speed of the project
        • contradicts the innovation speed goal
      • services become more and more dumber

Interview E:

  • No overwhelming ESB, but dumb ways to communicate
  • REST service, or something loosely coupled like a message queue