The System Design Newsletter

The System Design Newsletter

Everyone is a scalability expert till traffic spikes

#197: Part 1 - Break into scalability

Neo Kim's avatar
Neo Kim
Oct 29, 2026

Subscribe today & never miss a letter from me again!

  • Share this letter & I’ll send you some rewards for the referrals.


Once upon a time, there lived a junior software engineer named Michiko.

She worked for a tech company named Hooli.

Although she was bright, she never got promoted.

So she was sad & frustrated…

Until one day, she had the idea to apply for a new job.

And the interviewer asked her 1 simple question:

“How to effectively scale a system?”

But she couldn’t answer it & failed the interview in 5 minutes.

So she went home & studied it to fill the knowledge gap.

Onward.


Mermaid diagrams are the floor

Your coding agent can already paste a Mermaid chart into a PR description.

You still read every file to learn what it does to your system.

PR Lens draws each pull request as a live architecture canvas, right in your pull request. Press play and it walks you through the change, one step at a time.

On every PR, you see:

  • What changed, marked on the parts of the system it touches

  • What else it reaches, including services the diff never names

  • How a request moves through the system now

  • What could break, flagged before you merge

2,200+ GitHub stars and 45,000+ pull requests drawn.

Add it to your repo

(Thanks to Coldtea for partnering on this newsletter.)


Scalability Patterns in System Design

Michiko failed the interview, so you don’t have to.

And here are 11 must-know scalability techniques for you to ace job interviews:

1. Vertical scaling

Vertical scaling gives one machine more power by adding CPU, memory, and/or faster disks.

The app stays the same, but the machine it runs on gets more powerful... Or you move the app to a larger instance.

i.e., you do NOT need to rewrite any code. And vertical scaling is probably the quickest way to handle extra load.

It works well for monoliths & older systems built to run on a single machine.

Yet larger machines cost more & all machines have limits.

Plus, if your app relies on a single server, a failure could take the entire app down.

So scale up when you need more capacity quickly. Then consider horizontal scaling before one machine becomes your system’s biggest bottleneck.

2. Horizontal scaling

Horizontal scaling (scaling out) adds more machines to share the load.

You run several copies of the app & distribute traffic across them using a load balancer.

i.e., you add machines as traffic grows & remove them when demand drops.

It works well for applications with high/unpredictable traffic.

Yet adding machines creates new challenges:

You need load balancing, coordination between instances & keep shared data consistent.

Horizontal scaling improves “availability” with redundant instances. But if your app stores user sessions locally, requests routed to different instances could lose access to session data.

So before you scale out, you need to decide where your application stores its state.

And that’s why you’d need stateless services...

3. Stateless services

A stateless service does NOT store client session state between requests.

Every request provides information the server needs - auth token or session ID.

Plus, you don’t store session data on one server… instead, you keep it in a shared database, a cache like Redis, or use a signed token like a JSON Web Token (JWT).

i.e., any server could handle a request without relying on the previous one.

This makes it easier to add, remove, or replace servers as traffic patterns change.

Yet the state still needs to live somewhere.

And an external database/cache adds infrastructure, network latency & an extra dependency to manage. Plus, relying on sticky sessions to keep users tied to one server reduces flexibility when servers fail or traffic changes.

So keep session state outside individual app instances when possible. Also, design operations to be “idempotent”.

With stateless services, you could scale individual instances more easily.

But what if those services depend heavily on each other…

That’s where you’d need loose coupling...

4. Loose coupling

Loose coupling = each component depends on others as little as possible.

A change in one component could force you to update several others in a “tightly coupled” system.

Plus, if one service becomes slow/fails, the problem could spread to other services that depend on it.

Loose coupling reduces these dependencies by letting components communicate through well-defined interfaces - APIs/messages. So each component knows what to expect from others without understanding their internal implementation.

This makes it easier to update, deploy, and/or scale components independently.

Yet loose coupling introduces extra complexity:

Requests could travel across many services,,, thus making it HARD to trace & debug failures. Also,splitting a system into many tiny services increases communication overhead & coordination costs.

So use loose coupling when components need to evolve independently - microservices & big apps.

And to organize these components into clear, manageable parts, you need modular architecture…

5. Modular architecture

Modular architecture divides a system into separate modules, with each responsible for a specific function.

You divide the app into modules for authentication, orders, payments, notifications, and so on.

i.e., each module has a clear responsibility & communicates with others through defined interfaces.

The goal is to group functionality that belongs together & keep dependencies between modules minimal. This follows the principle of separation of concerns: each module focuses on one part of the system.

So you update/test payment module without changing the authentication module.

Yet choosing the “wrong module boundaries” creates unnecessary dependencies.

Plus, splitting an app into many modules makes the codebase hard to manage. Also, modules within the same app still share resources & failure risks.

So modularity alone does NOT guarantee independent scaling or failure isolation.

It works well for large applications, modular monoliths & microservice architectures!

But if these modules need to communicate without waiting for each other…you’d need event-driven architecture…


Subscribe now and be the first to know about my new letters & updates:


6. Event-driven architecture

Event-driven architecture allows services to communicate by publishing & reacting to events.

A service publishes an event to a message broker instead of calling other services directly.

Imagine a user places an order on an e-commerce website:

The order service publishes an OrderPlaced event… Then other services consume it independently:

  • Inventory service reserves ordered items,

  • Payment service initiates payment processing,

  • Notification service sends an order confirmation when required steps succeed.

Order service does NOT wait for each consumer to finish processing the event.

i.e., a slow consumer does NOT block others.

This approach works well for workflows when many services need to react to the same event.

Yet event-driven systems create new problems:

Events could arrive late, out of order, or more than once. Plus, different services could temporarily hold different versions of the same data. This is called eventual consistency.

So you need idempotent consumers, reliable event delivery & a way to handle failed operations.

Event-driven architecture helps services scale independently & reduces synchronous dependencies.

But when you need to organize these services without creating a central bottleneck, you’ve got to “avoid” centralized resources…


Like what you read? Share it with your friends & leave a comment!

Share


7. Shared-nothing architecture

Shared-nothing architecture gives each node its own compute, memory & storage without relying on shared resources for processing.

There are several ways to achieve this:

Subscribe for free to continue reading

Enter your email and get every post from The System Design Newsletter.
Already have an account? Sign in
© 2026 Neo Kim · Publisher Privacy
Substack · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture