03 / 12

What are the architecture patterns to achieve scalability?

Scalable architectures combine several proven patterns: horizontal scaling for stateless services, caching to reduce redundant work, sharding to partition data, asynchronous processing with message queues, read replicas for databases, and content delivery networks for static assets.

Achieving scalability requires a combination of architectural patterns applied at different layers of the system. No single pattern solves all scalability challenges; instead, a well-architected system layers these patterns to handle growth in users, data, and request volume. The patterns range from simple load balancing to complex data sharding, each addressing specific scalability bottlenecks.

Core Scalability Patterns
  1. 1

    Load Balancing: Distributes incoming requests across multiple servers. A load balancer sits in front of application servers, routing each request to an available instance. This is the foundation of horizontal scaling for stateless services. Algorithms include round-robin, least connections, and consistent hashing.

  2. 2

    Stateless Services: Services that don't store session data locally allow any instance to handle any request. Session state is externalized to shared storage (Redis, database) or client-side storage (cookies). This enables unlimited horizontal scaling.

  3. 3

    Caching: Stores frequently accessed data in fast, in-memory stores (Redis, Memcached) to reduce load on databases. Cache patterns include cache-aside (application manages cache), read-through (cache fetches from DB), and write-through (updates cache on write).

  4. 4

    Database Sharding (Horizontal Partitioning): Splits data across multiple database instances based on a shard key (e.g., user_id). Each shard holds a subset of data, allowing the system to scale beyond single-database limits. The shard key must be chosen carefully to distribute writes evenly.

  5. 5

    Read Replicas: Creates copies of the primary database that handle read queries. This separates read traffic from write traffic, allowing read-heavy workloads to scale horizontally while the primary handles writes. Replication lag must be managed.

  6. 6

    Asynchronous Processing: Uses message queues (RabbitMQ, Kafka, SQS) to decouple request handling from background work. The frontend quickly acknowledges requests, while workers process tasks asynchronously. This smooths traffic spikes and improves responsiveness.

  7. 7

    Microservices: Decomposes the application into independently deployable services, each focused on a specific business capability. Services can be scaled independently based on their own load patterns. This increases operational complexity but enables fine-grained scaling.

  8. 8

    Content Delivery Network (CDN): Caches static assets (images, CSS, JavaScript) at edge locations globally. This reduces load on origin servers and dramatically decreases latency for users worldwide.

  9. 9

    Auto-Scaling: Dynamically adjusts compute capacity based on current load. Instances are added when demand increases and removed when demand decreases. This optimizes cost while maintaining performance.

  10. 10

    Circuit Breaker: Prevents cascading failures by stopping requests to failing services. When a service is unhealthy, the circuit breaker opens, requests fail fast without waiting for timeouts, allowing the system to degrade gracefully.

Pattern Implementation Examples
Pattern Selection by Bottleneck
  1. 1

    Web server CPU-bound: Horizontal scaling with load balancer, auto-scaling groups

  2. 2

    Database read-heavy: Read replicas, caching layer (Redis), CDN for static content

  3. 3

    Database write-heavy: Sharding, partitioning, moving to distributed SQL databases

  4. 4

    External API dependencies: Asynchronous processing, circuit breakers, fallback caching

  5. 5

    Global user base: CDN for static assets, edge caching, geo-distributed database replicas

  6. 6

    Spiky traffic: Auto-scaling, message queues to smooth load, on-demand capacity

  7. 7

    Large dataset queries: Sharding, columnar storage, pre-computed aggregates

Scalability patterns often introduce complexity and trade-offs. Caching adds eventual consistency challenges—users may see stale data. Sharding makes cross-shard queries complex and can require application-level joins. Asynchronous processing adds complexity for error handling and retries. Microservices create network overhead and require distributed tracing. The art of scalable architecture lies in selecting the minimal set of patterns that address actual bottlenecks, not applying every pattern prematurely. Start simple, measure, and add patterns only when scaling limits are reached.

Difficulty: 8/10
Topics: horizontal scaling, stateless services, load balancing

Scenario Questions

0-2 years experience
  1. 1

    You're building a simple API that serves user profiles. Traffic just doubled — how would you make sure it doesn't slow down?

  2. 2

    Your web app is getting slow when 100 users hit it at once. You're running one server. What’s the first thing you’d try to fix it?

  3. 3

    If you had to deploy the same service across two servers, what would you need to change in your code to make it work?

2-5 years experience
  1. 1

    Your team deployed a new feature and now the API response times are spiking every hour — you’ve added more servers but it’s not helping. What’s your debugging approach?

  2. 2

    A microservice you own is stateful, and the product team wants to scale it quickly. How do you explain why that’s a problem and what you’d do instead?

  3. 3

    You’re seeing 502 errors during peak traffic. Your load balancer is configured with round-robin. What could be going wrong, and how would you investigate?

5-8 years experience
  1. 1

    You’re designing a real-time notification service that needs to handle 10x traffic growth in 6 months. What scaling architecture would you choose, and why not just throw more machines at it?

  2. 2

    Your team’s service uses a shared database and is hitting connection limits. How would you redesign the architecture to scale horizontally without introducing data inconsistency?

  3. 3

    You inherited a monolith that’s been horizontally scaled with sticky sessions. The ops team wants to remove them. What risks do you surface, and how would you migrate safely?

8+ years experience
  1. 1

    Your company’s core service has been scaled with stateless microservices for 5 years, but now the cost of managing 200+ instances is unsustainable. How would you redesign the architecture for long-term efficiency without sacrificing scalability?

  2. 2

    You’re leading the migration from a legacy load-balanced monolith to a service mesh. What tradeoffs do you weigh between operational complexity, observability, and scalability, and how do you get cross-team buy-in?

  3. 3

    A major partner’s traffic surge exposed a hidden bottleneck in your API gateway. You now need to scale globally. What architectural changes would you propose, and how do you ensure this design survives the next 10x growth without another overhaul?

Follow-up Questions

  • What happens if one of your backend instances crashes during a traffic spike?
  • How would you detect and respond to a load balancer becoming a bottleneck?
  • Why might adding more servers not improve performance in your system?