Software 13 min read

Boundary-First Service Design

Service boundaries are organizational and economic choices disguised as technical ones. Draw them from ownership and change cost before you split a codebase.

Start from change cost

Modules that change together belong together. If two "services" always deploy in lockstep because their models are entangled, the split bought you distributed monolith overhead with none of the independence.

Map the last quarter of changes: which files and teams always appear together? That map is a better service boundary than any domain-driven design diagram drawn in a workshop.

Contracts before containers

A service boundary is a contract: request and response shapes, error semantics, compatibility policy, and who may break them. Without that, every deploy is a negotiation.

Prefer versioned, boring APIs over clever shared libraries. Shared code across teams is coupling with a nicer name.

  • Define error types as part of the public contract.
  • Publish compatibility rules (additive changes only, deprecation windows).
  • Own the contract in one place; review changes like product changes.
  • Avoid sharing database tables across service boundaries.

Price the operational tax

Every extra service adds deployment, monitoring, tracing, secret management, on-call, and local development cost. That tax is fine when it buys independent scale or independent team velocity — not when it buys a diagram that looks modern.

A modular monolith with clear package boundaries often delivers the same team independence at a fraction of the operational cost.

If you cannot name the team that owns the on-call for a new service, do not create it.

Split when evidence says so

Good reasons to split: different scale characteristics, independent release cadence that is blocked by coupling, security isolation, or a clear ownership boundary already enforced in the org.

Bad reasons: resume-driven design, "best practices," or a dislike of the current codebase without a change-cost argument.

Key takeaways

  • Derive boundaries from co-change and ownership, not aesthetics.
  • Write contracts (errors and compatibility) before splitting code.
  • Budget the full operational tax of a new service.
  • Modular monoliths are a valid, often better, architecture.
  • Split on evidence: scale, cadence, isolation, ownership.