How do you draw service boundaries?
“You are splitting a system into services. What makes a boundary good, what makes it bad, and how would you find the right one for orders, inventory and payments?”
What this tests
- Boundary criteria: cohesion, change frequency, data ownership, team ownership
- Recognition of chatty boundaries and distributed transactions as boundary smells
- Domain-driven thinking without the vocabulary tour
- Willingness to keep things together when the boundary is not clear
Answers by level
Read the beginner answer first and notice what is missing.
A good boundary is one where the things inside change together and the things across it change rarely. Signs of a good boundary: a small, stable interface; the service can complete its core operation without calling others synchronously; it owns the data it needs to answer its own questions. Signs of a bad one: a request crosses it five times, two services need the same transaction, or a schema change on one side forces a deploy on the other.
Splitting by entity is the common mistake. "Order" and "OrderLine" and "Inventory reservation" are one workflow — placing an order — and separating them creates a distributed transaction on the happiest path in the system. I would draw boundaries by workflow and ownership instead: order placement (orders plus inventory reservation), payment capture (its own regulatory and provider concerns, different failure behaviour), fulfilment. Payments is a good boundary precisely because it changes for different reasons — provider integrations, PCI scope — and its interface is small: authorise, capture, refund.
When the boundary is not clear, keep the code together in a module and wait until the change patterns reveal it.
Green flags · Red flags
- Draws boundaries by workflow and reasons-for-change, not by entity
- Uses cross-boundary transactions and call counts as smells
- Ensures each service can answer its own questions from its own data
- Mentions team ownership as a boundary input
- Willing to defer a boundary that is not yet clear
- "One service per database table."
- Proposes a boundary that requires a distributed transaction on the main path
- Ignores the external payment provider's failure behaviour as a reason to isolate payments
- Cannot explain what data each service owns