Bird
Raised Fist0

Microservices vs Monolith - When to Split and the Hidden Costs

HLDmediumInterview freq: common
Choose your preparation mode4 modes available
🏗️
Microservices vs Monolith - When to Split and the Hidden Costs
Design decision framework for splitting monoliths into microservices with scale and cost trade-offs
mediumMicroservices InfrastructureFreq: common
⚙️
Functional Requirements
  • Support modular development and deployment of independent services
  • Enable independent scaling of components based on load
  • Provide clear service boundaries with well-defined APIs
  • Ensure fault isolation so failures in one service do not cascade
  • Support continuous integration and continuous deployment (CI/CD)
  • Allow for technology heterogeneity per service if needed
📊
Non-Functional Requirements
  • System must handle 2 billion daily active users (DAU)
  • Achieve 99.99% availability across services
  • Maintain 100ms P99 latency for user-facing API calls
  • Support 925K peak write QPS and 5M read QPS
  • Ensure data consistency within eventual consistency bounds
❓
Clarifying Questions to Ask
  • What is the current scale and growth trajectory of the system?
  • Are there existing pain points with the monolith (e.g., deployment, scaling)?
  • What is the tolerance for operational complexity and overhead?
  • Is there a need for polyglot persistence or technology heterogeneity?
  • What are the data consistency and transactional requirements?
  • How critical is fault isolation and independent service uptime?
Out of Scope
✗ Detailed implementation of individual microservices business logic
✗ Specific programming language or framework choices
✗ Infrastructure provisioning and cloud vendor selection
✗ Security policies beyond service-to-service authentication
📌
Assumptions
  • 2 billion DAU generating 40 messages per user per day
  • Average message size is 100 bytes
  • Peak write QPS is 10x average write QPS due to traffic spikes
  • Read QPS is 5x write QPS due to caching and fan-out
⚡
QPS Calculation
write qps2,000,000,000 × 40 / 86,400 ≈ 925,926 msg/sec
peak write qps925,926 × 10 = 9,259,260 msg/sec
read qps925,926 × 5 = 4,629,630 msg/sec
💾
Storage Estimate
daily storage gb(2,000,000,000 × 40 × 100) / (1024^3) ≈ 7,450 GB/day
retention days30
total storage gb7,450 × 30 = 223,500 GB
with replication223,500 × 3 (replication factor) = 670,500 GB
🖥️
Server Estimate
write db nodesAssuming Cassandra node handles 50K writes/sec, need 9,259,260 / 50,000 ≈ 186 nodes
api serversAssuming each API server handles 5,000 QPS, need 4,629,630 / 5,000 ≈ 926 servers
🏗️
Architecture Diagram
Architecture Diagram
          +----------------+
          |  Client Apps   |
          +-------+--------+
                  |
          +-------v--------+
          | API Gateway    |
          +-------+--------+
                  |
    +-------------+--------------+
    |                            |
 +--v---+                    +---v---+
 | Auth |                    | User  |
 | Svc  |                    | Svc   |
 +--+---+                    +---+---+
    |                            |
 +--v---+                    +---v---+
 | Kafka |                    | Redis |
 | Event |                    | Cache |
 | Bus   |                    +-------+
 +--+---+
    |
 +--v-----------------------------+
 | Cassandra Write-Optimized Store |
 +--------------------------------+
🧩
Components
API Gateway
Entry point routing client requests to appropriate microservices
Why thisEnvoy proxy supports dynamic routing, rate limiting, and observability at scale
Why notNginx lacks native service discovery and dynamic routing needed for microservices
Kafka Event Bus
Asynchronous communication and decoupling between microservices
Why thisKafka handles 10M+ messages/sec with durable, partitioned logs and consumer groups
Why notRabbitMQ does not scale linearly beyond 1M msg/sec and lacks durable log semantics
Cassandra Write-Optimized Store
Highly available, scalable storage for write-heavy workloads with eventual consistency
Why thisCassandra supports linear write scalability and multi-datacenter replication
Why notPostgreSQL requires complex manual sharding at 9M writes/sec; B-tree writes don't scale linearly
Redis Cache
Low-latency caching layer for hot data to reduce read load on databases
Why thisRedis TTL natively expires stale data without cron jobs - sub-millisecond lookup
Why notMemcached lacks persistence and advanced eviction policies needed for critical data
Authentication Service
Centralized user authentication and token issuance
Why thisOAuth2-compliant service with JWT tokens enables stateless auth across microservices
Why notIn-process auth in monolith causes tight coupling and scaling bottlenecks
User Service
Manages user profiles and preferences as an independent microservice
Why thisService isolation enables independent scaling and deployment of user-related features
Why notMonolith user module causes deployment delays and risk of cascading failures
🔄
Data Flow
1
Client Apps → API Gateway
Send user request (e.g., post message)
Gateway routes based on URL and auth token
2
API Gateway → Authentication Service
Validate user token
Ensures request is authenticated before processing
3
API Gateway → User Service
Forward request to user microservice
User service handles business logic for user data
4
User Service → Kafka Event Bus
Publish event for downstream processing
Decouples synchronous user logic from async processing
5
Kafka Event Bus → Cassandra Store
Consume event and persist data
Write-optimized storage for durability and scale
6
User Service → Redis Cache
Update cache with latest user data
Reduces read latency for hot user data
7
API Gateway → Client Apps
Return response with status and data
Completes request cycle with low latency

Practice

(1/5)
1. In the photo feed generation flow, at step 4 the Feed Worker fetches stories from the Stories Service cache. What happens if the cache TTL for a user's stories has expired at this step?
easy
A. The Feed Worker asynchronously refreshes the cache but returns an empty stories section immediately
B. The Feed Worker triggers a synchronous fetch from the Stories DB and blocks until fresh stories are retrieved
C. The Feed Worker returns stale stories from a backup cache without fetching fresh data
D. The Feed Worker skips stories for that user and proceeds with only photo posts in the feed

Solution

  1. Step 1: Trace Feed Worker behavior at cache miss

    When TTL expires, the cache is stale. The Feed Worker must avoid blocking feed generation.
  2. Step 2: Understand asynchronous cache refresh

    To maintain low latency, the Feed Worker returns empty stories immediately and triggers async cache refresh. Blocking fetch (B) would increase latency. Returning stale data (A) risks outdated content. Skipping stories silently (C) loses user experience.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Async cache refresh avoids blocking feed generation [check]
Hint: Async cache refresh avoids blocking feed generation [OK]
Common Mistakes:
2. In a CQRS system, a write request updates the primary database at Step 3. At Step 5, the read replica receives an update event. What is the state of the read replica at Step 6 immediately after receiving the event but before applying it?
easy
A. The read replica has already applied the update and serves the new data
B. The read replica rejects all reads until the update event is fully processed
C. The read replica switches to a read-only mode and queues incoming reads
D. The read replica still serves stale data until the update event is applied

Solution

  1. Step 1: Trace event arrival at read replica

    Upon receiving the update event, the read replica has not yet applied it, so data is stale.
  2. Step 2: Understand read replica behavior

    Read replicas serve stale data until the event is processed; they do not reject or queue reads.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Read replicas serve stale data until update applied [check]
Hint: Read replicas lag briefly, serve stale data until updated [check]
Common Mistakes:
3. For ranking posts in a Reddit-like system with millions of votes per minute, which architecture better balances real-time freshness and scalability?
medium
A. Use a streaming pipeline (Kafka + Flink) to incrementally update scores asynchronously
B. Use batch jobs every hour to recompute rankings from raw vote data
C. Use a single centralized database to compute ranking scores on every vote synchronously
D. Use client-side ranking computation to reduce server load

Solution

  1. Step 1: Evaluate synchronous centralized DB approach

    Use a single centralized database to compute ranking scores on every vote synchronously causes write bottlenecks and high latency, unsuitable for millions of votes per minute.
  2. Step 2: Compare streaming vs batch and client-side

    Batch (Use batch jobs every hour to recompute rankings from raw vote data) has high latency, unsuitable for real-time freshness. Client-side (Use client-side ranking computation to reduce server load) can't guarantee consistent global ranking. Streaming pipeline (Use a streaming pipeline (Kafka + Flink) to incrementally update scores asynchronously) provides near real-time incremental updates and scales horizontally.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Streaming pipelines enable scalable, near real-time ranking updates [check]
Hint: Streaming pipelines scale and update rankings near real-time [check]
Common Mistakes:
4. For timeline generation at scale, which architecture better handles users with millions of followers and why?
medium
A. Pure pull-based: generate timelines on-demand by querying follow graph and tweets
B. Push-based fan-out: write each tweet to all followers' timelines synchronously
C. Hybrid approach: push fan-out for users with few followers, pull on read for celebrities
D. Store timelines in a global sorted set updated asynchronously for all users

Solution

  1. Step 1: Analyze push vs pull trade-offs

    Push fan-out is efficient for low-follower users but expensive for celebrities; pull is costly on read latency.
  2. Step 2: Evaluate hybrid approach

    Hybrid uses push for most users, pull for celebrities, balancing latency and write amplification.
  3. Step 3: Eliminate other options

    Pure push (A) causes huge write amplification; pure pull (C) causes high read latency; global sorted set (D) is hard to scale and update asynchronously.
  4. Final Answer:

    Option C -> Option C
  5. Quick Check:

    Hybrid push-pull balances write cost and read latency [check]
Hint: Hybrid push-pull fits follower count extremes [check]
Common Mistakes:
5. If the API Gateway component is removed from a microservices architecture that relies on it for authentication and rate limiting, what is the most likely failure mode?
medium
A. Backend services will automatically reject unauthorized requests, so no failure occurs
B. Clients will be able to send unlimited requests directly to backend services, causing overload and security breaches
C. Reverse Proxy will cache authentication tokens, leading to stale authorization decisions
D. Load Balancer will take over authentication, causing increased latency but no security issues

Solution

  1. Step 1: Understand API Gateway role

    API Gateway centralizes authentication and rate limiting; without it, these controls are lost.
  2. Step 2: Trace failure consequences

    Load Balancer does not perform authentication but may attempt to handle some traffic control, increasing latency; backend services may be exposed to unauthorized requests.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Removing API Gateway removes centralized auth, Load Balancer can't fully compensate [check]
Hint: No API Gateway -> Load Balancer tries but can't secure backend [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard