πŸ“š Table of Contents

  1. The Architecture That Ate a Company
  2. What Monolith and Microservices Actually Mean
  3. The Honest Truth About Each Approach
  4. When to Choose Monolith (The Case for Starting Simple)
  5. When to Choose Microservices (The Real Triggers)
  6. The Organizational Impact Nobody Talks About
  7. The Migration Path: From Monolith to Microservices
  8. Common Mistakes andAnd How to Avoid Them
  9. Questions to Ask Your Engineering Team
  10. The Decision Framework
  11. The Bottom Line

The Architecture That Ate a Company

In 2021, a promising startup made a decision that nearly killed them.

They had $2M in funding, 5 engineers, and a product roadmap that could get them to Series A. The CTO, fresh from a large tech company, insisted on building microservices from day one.

“We need to be ready to scale,” he said. “Netflix uses microservices. We should too.”

Six months later:

  • 47 microservices for a product that had 3 user-facing features
  • 4 different databases
  • Complexity that required 20 engineers to maintain
  • Development velocity had dropped to near zero
  • They’d spent $1.2M of their $2M funding

The post-mortem: They’d optimized for a scale they never reached, sacrificing the speed they desperately needed.

The naked truth: Most companies should start with a monolith. Many never need microservices. The ones that do usually transition too late or too earlyβ€”rarely at the right time.

This guide will help you understand when that right time is.


What Monolith and Microservices Actually Mean

Monolith: The Single Unit

What it is: One codebase, one deployable unit, one database (usually).

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MONOLITHIC APPLICATION                                   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ User Serviceβ”‚   β”‚ Order Service β”‚   β”‚ Payment      β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                         β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚                Single Database                      β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚                                                         β”‚
β”‚  One codebase. One deployment. Scale as a unit.          β”‚
β”‚                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Characteristics:

  • Single deployable artifact
  • All features in one codebase
  • Typically one database
  • In-memory function calls between components
  • Scales as a single unit

Microservices: The Distributed System

What it is: Multiple independent services, each with its own codebase, database, and deployment.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ MICROSERVICES ARCHITECTURE                                        β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                                     β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚  β”‚ User Serviceβ”‚  β”‚ Order Serviceβ”‚  β”‚ Payment Svcβ”‚  β”‚ Email Svc   β”‚ β”‚
β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚  β”‚             β”‚ β”‚
β”‚  β”‚ [User DB]   β”‚  β”‚ [Order DB]  β”‚  β”‚ [Payment DB]β”‚  β”‚ [Queue]     β”‚ β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚         β”‚                β”‚                β”‚                β”‚        β”‚
β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜        β”‚
β”‚                              Network Communication                   β”‚
β”‚                                                                     β”‚
β”‚  Independent deployments. Independent scaling. Network calls.      β”‚
β”‚                                                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Characteristics:

  • Multiple deployable artifacts
  • Each service has its own database
  • Communication via network (HTTP, gRPC, events)
  • Independent scaling
  • Requires infrastructure coordination

The Honest Truth About Each Approach

Monolith: The Honest Pros and Cons

ProsCons
βœ… Simpler development❌ Single point of failure
βœ… Easier debugging❌ Technology lock-in
βœ… Simpler deployment❌ Scaling everything together
βœ… Lower operational overhead❌ Larger blast radius for bugs
βœ… Faster initial development❌ Can become a “big ball of mud”
βœ… Easier to hire for❌ Team coordination at scale
βœ… Lower cloud costs initially❌ Harder to adopt new tech

Microservices: The Honest Pros and Cons

ProsCons
βœ… Independent scaling❌ Distributed system complexity
βœ… Technology flexibility❌ Operational overhead
βœ… Team autonomy❌ Network latency and failures
βœ… Fault isolation❌ Harder debugging
βœ… Smaller blast radius❌ Higher infrastructure costs
βœ… Clear boundaries❌ Data consistency challenges
βœ… Can scale teams❌ Requires mature DevOps

The Hidden Costs of Microservices

Infrastructure costs: 2-5x higher than monolith

  • Multiple databases
  • Service mesh or API gateways
  • Monitoring for each service
  • Network overhead

Engineering costs: Higher headcount needed

  • DevOps engineers
  • Platform engineers
  • Service owners

Cognitive costs: Harder to understand the system

  • Where does this data come from?
  • Which service owns this?
  • How do these 47 services interact?

When to Choose Monolith (The Case for Starting Simple)

The Strong Cases for Monolith

You’re early-stage (< 20 engineers)

  • Velocity matters more than scale
  • Complexity kills early-stage companies
  • You don’t know your product yet

Your domain is well-bounded

  • Clear business domain
  • Limited integration points
  • Predictable scaling needs

You have limited DevOps maturity

  • No dedicated platform team
  • Limited infrastructure expertise
  • Simple deployment pipeline

Speed is your competitive advantage

  • Need to iterate fast
  • Product-market fit uncertain
  • Time to market matters more than efficiency

The Monolith Decision Checklist

Choose monolith if most of these are true:

  • Fewer than 20 engineers
  • No dedicated DevOps team
  • Product-market fit not established
  • Limited operational budget
  • Team co-located (same timezone)
  • Simple domain, clear boundaries
  • Haven’t hit scaling problems yet

When to Choose Microservices (The Real Triggers)

The Strong Cases for Microservices

You’ve hit actual scaling bottlenecks

  • One component needs 10x the resources of others
  • Database is the bottleneck, can’t scale horizontally
  • Specific services need different scaling characteristics

You have organizational scale

  • 50+ engineers
  • Multiple teams stepping on each other
  • Deployment coordination is painful

Different components have different requirements

  • One service needs real-time processing
  • Another needs heavy computation
  • Different uptime requirements by component

You need technology flexibility

  • Some features benefit from Go
  • Others need Python for ML
  • Different database needs by domain

The Real Triggers (Not the Aspirational Ones)

Trigger 1: Deployment Bottleneck

“We deploy once every 2 weeks because coordinating releases takes forever.”

β†’ Microservices allow independent deployment

Trigger 2: Scaling Imbalance

“Our notification service handles 1M messages/day. Our payment service handles 10K. But we scale them together.”

β†’ Microservices allow independent scaling

Trigger 3: Team Autonomy

“Three teams work on the same codebase. Every PR affects everyone. We spend more time coordinating than coding.”

β†’ Microservices allow team ownership

Trigger 4: Different SLAs

“Our search feature can tolerate 99.5% uptime. Our payment system needs 99.99%. But we deploy them together.”

β†’ Microservices allow different reliability levels


The Organizational Impact Nobody Talks About

Conway’s Law in Action

“Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.”

What this means: Your architecture will match your organization.

Four engineers, monolith: Simple, because communication is simple Fifty engineers, monolith: Chaos, because communication is complex Fifty engineers, microservices: Possible order, because each team owns its service

The Team Structure Impact

ArchitectureTeam StructureCommunication
MonolithOne or two teamsSimple, synchronous
MicroservicesOne team per serviceComplex, asynchronous
HybridDomain-aligned teamsBalanced

The Hiring Implications

Monolith:

  • Hire generalists who understand the full system
  • Easier to find talent
  • Lower salary expectations
  • Faster onboarding

Microservices:

  • Need specialists (DevOps, platform engineers)
  • Harder to find talent
  • Higher salary expectations
  • Slower onboarding (each service is different)

The Migration Path: From Monolith to Microservices

When to Migrate

Don’t migrate preemptively. Migrate when you feel the pain.

Signs it’s time:

  • Deployment coordination takes days
  • One component’s scale issues affect everything
  • Teams are blocked by each other
  • You have a dedicated platform team

The Strangler Fig Pattern

The safe way to migrate:

Phase 1: Identify boundary
β”œβ”€β”€ What service can be extracted?
β”œβ”€β”€ Clear domain boundary?
└── Minimal dependencies?

Phase 2: Build new service alongside
β”œβ”€β”€ New service for new functionality
β”œβ”€β”€ Strangler fig: Route new requests to new service
└── Keep old code for old requests

Phase 3: Gradually migrate
β”œβ”€β”€ Route more traffic to new service
β”œβ”€β”€ Monitor for issues
└── Keep fallback ready

Phase 4: Decommission old code
β”œβ”€β”€ When 100% traffic on new service
β”œβ”€β”€ Remove old code
└── Celebrate πŸŽ‰

The Migration Timeline Reality

Optimistic estimate: 3-6 months
Realistic estimate: 12-18 months
Actual time: 18-36 months (usually)

Budget for:

  • Reduced feature velocity during migration
  • Additional infrastructure costs
  • Training and documentation
  • Rollback scenarios

Common Mistakes (And How to Avoid Them)

Mistake 1: Premature Decomposition

What happens: Splitting into microservices before understanding the domain.

The result: Services have unclear boundaries. Distributed monolith. Network calls everywhere.

How to avoid: Start with a monolith. Extract services when boundaries become clear through actual development.


Mistake 2: Distributed Monolith

What happens: Services that can’t operate independently. Every deployment requires coordinating multiple services.

The result: All the complexity of microservices, none of the benefits.

How to avoid: Ensure each service can be deployed independently. If deploying one requires deploying another, they should probably be one service.


Mistake 3: Wrong Boundaries

What happens: Services split by technical layer (frontend, backend, database) instead of business domain.

The result: A simple change requires touching multiple services. Network latency for everything.

How to avoid: Split by business domain (User, Order, Payment), not technical layer.


Mistake 4: Ignoring Data Consistency

What happens: Services have their own databases. Data becomes inconsistent across services.

The result: Users see different data in different parts of the app. Customer support nightmare.

How to avoid: Design for eventual consistency. Implement sagas for distributed transactions. Have a single source of truth for critical data.


Mistake 5: Underestimating Operational Complexity

What happens: Split services, realize you need service discovery, API gateways, distributed tracing, centralized logging…

The result: Infrastructure takes more engineering time than product features.

How to avoid: Have a platform team before microservices. Or use managed services (Kubernetes, ECS) that handle some complexity.


Questions to Ask Your Engineering Team

About Current Architecture

  • “Are we a monolith or microservices? How did we get here?”
  • “What are the pain points with our current architecture?”
  • “What would change if we switched architectures?”

About Scaling

  • “Where are our scaling bottlenecks?”
  • “Do all parts of our system scale together?”
  • “What’s the cost of our current architecture?”

About Team Impact

  • “How does our architecture affect team autonomy?”
  • “How long does a typical deployment take?”
  • “How often do teams block each other?”

About Migration

  • “Have we considered migrating? What stopped us?”
  • “What would a migration timeline look like?”
  • “What resources would we need?”

The Decision Framework

The Architecture Decision Canvas

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ARCHITECTURE DECISION CANVAS                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚                                                         β”‚
β”‚  CURRENT STATE                                         β”‚
β”‚  β”œβ”€β”€ Team size: _____                                   β”‚
β”‚  β”œβ”€β”€ Engineer count: _____                              β”‚
β”‚  β”œβ”€β”€ Services: _____                                    β”‚
β”‚  β”œβ”€β”€ Deployment frequency: _____                        β”‚
β”‚  └── Pain points: ___________________                   β”‚
β”‚                                                         β”‚
β”‚  PRODUCT NEEDS                                          β”‚
β”‚  β”œβ”€β”€ Scaling requirements: _____                        β”‚
β”‚  β”œβ”€β”€ Feature velocity needed: _____                     β”‚
β”‚  β”œβ”€β”€ Reliability requirements: _____                    β”‚
β”‚  └── Technology flexibility needs: _____               β”‚
β”‚                                                         β”‚
β”‚  ORGANIZATIONAL CONTEXT                                β”‚
β”‚  β”œβ”€β”€ DevOps maturity: Low / Medium / High               β”‚
β”‚  β”œβ”€β”€ Platform team: Yes / No                            β”‚
β”‚  β”œβ”€β”€ Budget constraints: _____                          β”‚
β”‚  └── Timeline pressure: Low / Medium / High              β”‚
β”‚                                                         β”‚
β”‚  RECOMMENDATION                                        β”‚
β”‚  β”œβ”€β”€ Monolith: If team <20, velocity-critical          β”‚
β”‚  β”œβ”€β”€ Microservices: If scaling bottleneck, team >50     β”‚
β”‚  └── Hybrid: Transitioning, unclear boundaries          β”‚
β”‚                                                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The Honest Recommendation

Your SituationRecommendation
<10 engineers, early-stageMonolith, 100%
10-20 engineers, growingMonolith with clear boundaries
20-50 engineers, scaling painStart extracting services
50+ engineers, multiple teamsMicroservices if you have platform team
Any size, no DevOpsMonolith until you build DevOps

The Bottom Line

Architecture is not a technical decision. It’s a business decision with technical implications.

Choose monolith when:

  • Velocity is more important than scale
  • Team is small (<20 engineers)
  • Product-market fit is uncertain
  • DevOps maturity is low

Choose microservices when:

  • You have actual scaling bottlenecks
  • Team size requires autonomy (>50 engineers)
  • You have a dedicated platform team
  • Different components need different technologies

The most important rule: Don’t optimize for scale you don’t have. Optimize for the velocity you need.

Your architecture should enable your product strategy, not constrain it. If your architecture is slowing you down, it’s time to reconsider.


What architecture is your team using? What pain points are you feeling?

Related Reading: