Design and Decomposition Questions
How do you decide service boundaries?
- Business capability: catalogue, ordering, payments, users, notifications.
- DDD bounded context: the place where a word has one meaning. "Product" in catalogue (description, images) differs from "Product" in order (id, price at purchase time).
- High cohesion inside, loose coupling outside: if two services always change together or call each other chattily, merge them.
- Team ownership (Conway's law): one team can own a service end to end.
Why database per service? How do you query data owned by another service?
Shared databases couple services at the schema level: one team's migration breaks another service, and nobody owns the data. With database per service, only the owner touches its tables. To read others' data use:
- API call (order-service calls product-service for the price).
- API composition at the gateway/BFF for read screens.
- Data replication by events: order-service keeps a local read copy of product names updated from
ProductUpdatedevents (CQRS read model).
What is a distributed monolith and how do you avoid it?
Services that are split physically but still coupled: shared database, synchronous call chains (A → B → C → D) for every request, shared domain library, lock-step deployments. Avoid it with clear bounded contexts, own data, async events for side effects, backward-compatible API versions and consumer-driven contract tests.
How do you version microservice APIs without breaking clients?
- Prefer backward-compatible changes: add optional fields, never rename or remove; consumers ignore unknown fields (Jackson
FAIL_ON_UNKNOWN_PROPERTIES=false, Boot's default). - For breaking changes, run
/api/v1and/api/v2side by side (URI or header versioning) and retire v1 after clients migrate. - Verify with consumer-driven contract tests (Spring Cloud Contract, Pact) in CI.
How would you migrate a monolith to microservices?
Use the strangler fig pattern: put a gateway in front of the monolith, build one new service (start with a low-risk, well-bounded module like notifications or catalogue), route its paths to the new service, sync data via events or CDC, and repeat until the monolith is gone or small.
client ─► gateway ─┬─ /api/products/** ─► product-service (new)
└─ everything else ─► monolith (shrinking)What is the Backend for Frontend (BFF) pattern?
A separate gateway-like service per client type (web, mobile, partner). Each BFF aggregates and shapes data for its UI: the mobile BFF returns a lighter product card, the web BFF returns full details plus recommendations. It keeps client-specific logic out of the core services. Used by apps like Swiggy and Netflix where mobile and web screens differ a lot.