Splitting an app into microservices sounds easy — until you try it. Draw the boundaries wrong and you get a distributed mess that's harder to run than the monolith you started with. This post covers the 5 ideas that help you draw those lines well, using Swiggy.
The 5 ideas
| # | Concept | One-line |
|---|---|---|
| 1 | DDD (bounded contexts) | Split by business domain, not tech |
| 2 | Strangler Fig | Safely kill a monolith piece by piece |
| 3 | Anti-Corruption Layer | A translator guarding your clean model from a messy one |
| 4 | BFF (Backend-for-Frontend) | A tailored backend per client (mobile vs web) |
| 5 | API Gateway | One front door for all services |
1. DDD — Bounded Contexts
The core skill: split services by business domain, not by technical layer.
The word "order" means different things in different parts of Swiggy. DDD says: let each area own its own meaning.
❌ Wrong split (by tech): [All Controllers] [All Databases] [All Logic]
✅ Right split (by domain): [Ordering] [Delivery] [Payments] [Restaurant]
A bounded context = a boundary where a word has ONE clear meaning.
| Word | In Ordering | In Delivery |
|---|---|---|
| "Order" | items + price + cart | pickup + drop location + route |
Same word, different meaning per context. Each context is a candidate microservice.
| ✅ Good | ❌ Bad |
|---|---|
| Boundaries match the business | Needs deep domain knowledge |
| Teams own a whole domain | Over-splitting early = pain |
Swiggy: Ordering, Delivery, Payments, Restaurant Onboarding, Search — each a bounded context, each a team.
The rule: find where the language changes → that's a boundary.
2. Strangler Fig
Kill a monolith gradually — never a risky big-bang rewrite.
Named after a vine that grows around a tree and slowly replaces it. You wrap the old system, peel off one feature at a time, until the monolith is gone.
Step 1: [Monolith] ← all traffic
Step 2: [Facade] → routes SEARCH to a new service, rest to monolith
Step 3: more features moved out...
Step 4: [Monolith gone] — all services new
| ✅ Good | ❌ Bad |
|---|---|
| Low risk, one piece at a time | Slow, takes patience |
| Ship continuously | Two systems run in parallel for a while |
| Roll back easily | The facade adds complexity |
Swiggy: moving from a 2014 monolith to microservices. You don't rewrite overnight; you strangle it feature by feature.
Azure: API Management as the facade — routes some paths to the old app, some to new services.
3. Anti-Corruption Layer (ACL)
A translator that stops a messy external system from polluting your clean model.
When you integrate with a third party (or a legacy system) whose data model is ugly, you don't let their mess leak into your code. You put a translation layer in between.
[Your clean Payment model] ← ACL translates → [Messy external bank API]
| ✅ Good | ❌ Bad |
|---|---|
| Your domain stays clean | Extra layer to build/maintain |
| Swap the external system without touching your core | Translation adds a little latency |
Swiggy: integrating a payment gateway or a legacy restaurant POS that returns weird formats. The ACL converts their mess into your clean shape — the Order service never sees the ugliness.
4. BFF — Backend-for-Frontend
A separate, tailored backend for each type of client.
A mobile app and a web dashboard need different data shapes. Instead of one bloated API serving both badly, give each its own backend.
[Mobile App] → [Mobile BFF] ─┐
[Web App] → [Web BFF] ─┼→ shared microservices
[Partner App]→ [Partner BFF] ─┘
| ✅ Good | ❌ Bad |
|---|---|
| Each client gets exactly what it needs | More backends to maintain |
| Mobile gets light payloads | Some logic duplicated |
| Change one client without breaking others | — |
Swiggy: the customer app, the delivery-partner app, and the restaurant dashboard each hit their own BFF — mobile gets tiny payloads, the dashboard gets rich data. Same core services underneath.
5. API Gateway
One front door for all your services.
Clients don't call 20 services directly. They hit ONE gateway, which routes, secures, and manages everything.
Clients → [ API Gateway ] → [order] [payment] [search] [delivery]
What it handles in one place:
| Job | Meaning |
|---|---|
| Routing | Send each request to the right service |
| Auth | Check tokens once, centrally |
| Rate limiting | Stop abuse |
| SSL termination | Handle HTTPS here |
| Aggregation | Combine several service calls into one |
| ✅ Good | ❌ Bad |
|---|---|
| One place for cross-cutting concerns | A single point of failure (must be highly available) |
| Clients don't know the internal layout | Can become a bottleneck |
Azure: this is API Management (APIM).
Gateway vs BFF (the confusion everyone has)
| API Gateway | BFF | |
|---|---|---|
| How many? | One for everyone | One per client type |
| Job | Route + secure + manage | Shape data for a specific client |
| Analogy | The building's main reception | A personal assistant per VIP |
They stack: clients → their BFF → the gateway → services. BFF shapes; gateway routes.
How it all fits together
[Mobile] → [Mobile BFF] ─┐
[Web] → [Web BFF] ─┼→ [API Gateway] → microservices split by [Bounded Contexts]
↑
(Strangler Fig built these by peeling off the monolith)
(ACL guards each service from messy external systems)
The whole thing in one line
Draw service boundaries where the business language changes (DDD), migrate to them safely (Strangler Fig), shield them from messy outsiders (ACL), give each client a tailored backend (BFF), and put one front door in front of it all (API Gateway). Get the lines right, and microservices actually pay off.
Top comments (0)