Overview

13 Guidance on microservices

This chapter distills practical security guidance for microservices: define services as small, business‑oriented components with independent runtimes and deployments, and design them to tolerate partial failure. It cautions against creating a distributed monolith and emphasizes three often-overlooked properties—independent runtimes, independent updates, and being designed for down—using patterns like bulkheads, circuit breakers, and event-driven messaging to keep the system resilient.

A core theme is treating each service as a bounded context and exposing only domain operations in public APIs so the service can enforce invariants itself. This promotes clear ownership of concepts, explicit translation across contexts, and safer evolution over time. Guidance includes splitting monoliths along semantic boundaries, validating and translating inputs at service borders with strong domain types, and evolving semantics without breaking context mappings—thereby avoiding ripple effects and subtle security defects.

The chapter also examines cross-cutting data concerns through the CIA-T lens. For confidentiality, propagate caller identity across calls with tokens and assess sensitivity as context-dependent, especially in aggregating services. For integrity and availability, favor authoritative sources, cryptographic checks, and defensive patterns. Achieving traceability requires unique service identity (name, version, instance) and transaction correlation IDs across systems. Finally, it promotes structured, domain-oriented logging performed inside each service, optionally signed to attest integrity, and categorized into separate streams (such as audit, behavior, and error) to prevent leakage of sensitive information and to enable strict access control, especially for long‑lived audit data.

Figure 13.1. Log data is transformed into JSON in an external normalization step.
ch13 external normalization small
Figure 13.2. Log data is structured into JSON before being passed to the logging system.
ch13 json to logging system small
Figure 13.3. The unique trace ID is shared between systems A, B, and C.
ch13 shared trace id small

 Summary

  • A good microservice should have an independent runtime, allow independent updates, and be designed for other services being down.
  • Treating each microservice as a bounded context helps you design more secure APIs.
  • Secure design principles such as domain primitives and context mapping are also applicable when designing microservice APIs.
  • In order to avoid common security pitfalls, only expose domain operations in APIs, use explicit context mapping between services, and pay extra attention to evolving APIs.
  • It’s important to analyze confidentiality, integrity, availability, and traceability (CIA-T) across all services.
  • Identify data that’s sensitive and possibly needs to be secured across services.
  • The integrity of log data is important from a security standpoint.
  • Normalization and categorization of log data requires extensive domain knowledge and should be part of the service design.
  • A service must be uniquely identifiable by its name, version number, and instance ID.
  • A transaction must be traceable across systems.
  • Using a logger with a domain-oriented API facilitates a design that considers the confidentiality of log data.
  • Don’t intermix sensitive and nonsensitive data in the same log because it can lead to accidental information leakage.

FAQ

What defines a well-designed microservice, and how do I avoid creating a “distributed monolith”?A well-designed microservice is a small, business-aligned service that runs in an independent runtime, is loosely coupled, and is independently deployable. A distributed monolith emerges when services depend on each other’s startup order, share hidden coupling, or must be deployed together. Aim for independent runtimes, stable contracts, and minimal cross-service assumptions to avoid this anti-pattern.
Why treat each microservice as a bounded context?Modeling each service as a bounded context clarifies its language, rules, and invariants, which leads to tighter, safer APIs. It forces explicit translation at service boundaries (for example, via domain primitives), reducing semantic leaks and security issues. It also makes slicing features and evolving services easier and safer.
How should I design microservice APIs to enforce invariants (instead of CRUD)?Expose domain operations that reflect business actions, not generic setters/getters or raw CRUD on internal state. For example, record “legal agreement added” or “payment confirmed” and derive activation from those facts, rather than letting callers flip an “activated” flag. This keeps invariants inside the service, prevents invalid states, and lets you add new preconditions without breaking clients.
What’s the secure approach to splitting a monolith into microservices?Identify semantic boundaries first, then extract along those lines. Introduce domain primitives and explicit validation at the new service edges so translations between contexts are deliberate, not implicit. Ensure the new APIs reflect domain operations, not leaked internals from the monolith.
How do I evolve services and semantics without causing security problems?Track context mappings and update translations when semantics change. Don’t redefine existing terms in place; introduce new terms or versions to reflect new meanings and deprecate the old. Test cross-service flows for subtle meaning changes that could lead to authorization, pricing, or policy errors.
What do “independent runtimes” and “independent updates” mean in practice?Each service runs in its own process/container with no start-order or location assumptions about others, allowing one to restart or move without impacting the rest. Changes should usually touch one service (or a small set) and be deployed independently. Cloud-native and 12-factor practices help achieve this.
What does “designed for down” mean, and which patterns help?Assume dependencies will be unavailable and make failure a first-class scenario. Use bulkheads to contain failures, circuit breakers to prevent cascades, timeouts/fallbacks or cached values for resilience, and event-driven messaging to decouple availability between sender and receiver. Implement and test degraded-mode behavior early.
How do I identify and protect sensitive data across services using CIA-T?Think system-wide: confidentiality requires carrying the caller’s identity and authorization across hops (for example, OAuth 2.0 with JWT). Integrity improves when you read from authoritative sources and use checksums/signatures to detect tampering. Availability needs timeouts, retries, and sensible defaults. Traceability requires recording who did what, correlated across services.
How can I ensure integrity and traceability of logs in a microservice architecture?Log structured data (such as JSON) in each service and avoid free-form strings. Include service name, version, and a unique instance ID in each entry and sign payloads (for example, with SHA-256/HMAC) so the origin and contents can be verified. Propagate a unique transaction/trace ID across services to correlate end-to-end activity in aggregated logs.
Why use a domain-oriented logger API, and how should logs be separated?A domain-oriented logger guides developers to log the right facts (for example, “bookingCancelled”) and to pre-categorize entries (Audit, Behavior, Error). Only Audit may contain sensitive data; never mix sensitive and non-sensitive categories in the same stream. Store categories as separate log streams, apply strict access control and longer retention to audit logs, and scrub stack traces or inputs that might leak confidential data.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secure by Design ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secure by Design ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Secure by Design ebook for free