"We're going to split this into microservices" is one of the most consequential architectural decisions a team makes, and one of the least quantified. The pitch deck shows boxes with arrows. The Jira board shows epics with story points. What does not show up anywhere — until ~9 months in, when the migration is half-complete — is the actual cost and latency profile of the post-migration system.
The good news is that the math is computable at design time. The cost of an inter-service call is well-defined. The latency added by a network hop is well-defined. What's missing is the discipline to actually compute it before committing.
The hidden costs of microservices
- Inter-service network cost. Every call that used to be a function invocation is now an HTTP/gRPC request. Cross-AZ at $0.01/GB each direction. At scale this is a five-figure-per-month line item.
- Observability cost. Distributed tracing, log aggregation, metric cardinality. Datadog or X-Ray bills inflate 3–5× post-migration as the service count goes up.
- Latency tax. Each hop adds 2–8 ms. A request that touched 1 service now touches 7. p99 grows linearly with hop count when downstream services are anything but boringly healthy.
- Database fanout. One DB connection per service. Connection pool sizing becomes a coordination problem.
- Deployment complexity. CI/CD pipelines multiply. Service-to-service version compatibility becomes a runtime concern, not a compile-time one.
Pre-migration simulation: monolith vs microservices
Same workload (10K RPS), same database, same business logic. Modelled on the pinpole canvas:
| Metric | Monolith (ECS, 20 tasks) | Microservices (12 services, 4 tasks each) |
|---|---|---|
| Compute | $1,400/mo | $3,360/mo |
| Inter-service data transfer | $0 | $680/mo |
| Load balancer (1 ALB vs 12) | $25/mo | $300/mo |
| Observability | $400/mo | $1,400/mo |
| p99 latency (warm) | 120ms | 340ms |
| Failure surface (services that can break a request) | 1 | 7 |
The microservices version is 2.5× the cost and 3× the latency for the same workload. The gain is autonomy: smaller blast radii, parallel team work, independent deployment. Those are real benefits — but they need to be honestly weighed against the numbers.
When the migration is worth it
Worth it
Engineering organisation has >30 people, multiple product domains, painful deployment coordination, scaling needs that genuinely differ by domain.
Often not worth it
Sub-20-person team chasing "scalability" they don't have measured traffic for. "We want to be Netflix" is not a strategy.
Definitely not worth it
The team's current pain is code complexity, not deployment coupling. A modular monolith solves the same problem with none of the operational overhead.
The pre-migration test
- Model the post-migration architecture on a canvas — every service, every database, every inter-service call.
- Run the simulation at your real traffic — get cost and p99.
- Compare against the current monolith — same traffic, same canvas.
- Multiply the migration effort estimate by 2. Then ask if the delta still makes sense given honest organisational benefits.
Of every microservices migration we have seen finished in the last three years, the most common honest retrospective answer to "would you do it again?" is "we'd do a modular monolith first." Not because microservices are wrong — because the team wasn't ready, the traffic didn't justify it, or the organisational benefits never materialised.
Simulating the migration on pinpole
Build both canvases. Save them as version snapshots. Run the same traffic through both. The pinpole comparison view diffs cost and latency side by side. Every architectural decision in the migration plan can be validated this way — including the "modular monolith first, microservices later" path.
The most expensive architecture decision is the one made on a whiteboard.
Simulate the post-migration architecture before you start the migration. Pinpole's canvas surfaces cost and latency at design time.
Start 14-day free trial →