DEV Community

Cover image for What Happens When Your API Suddenly Gets 10 Million Requests?
Derek mwale
Derek mwale

Posted on

What Happens When Your API Suddenly Gets 10 Million Requests?

What Happens When Your API Suddenly Gets 10 Million Requests?

One of the most interesting things about software engineering is that success creates new problems.

A small application has simple problems.

The database is slow.

A query needs optimization.

A page takes too long to load.

A user reports a bug.

Then something unexpected happens.

People actually start using your product.

Thousands become hundreds of thousands.

Hundreds of thousands become millions.

Suddenly, the problems change.

Your code didn't suddenly become worse.

The system simply entered a different world.

An API that worked perfectly yesterday might collapse tomorrow because the number of requests has changed.

This is where system design becomes real.

Because scaling isn't about adding more servers.

It's about understanding where pressure appears, how systems fail, and how we design software that can continue serving users even when demand grows beyond our expectations.

So let's imagine something simple.

We built a social media API.

Users can:

  • Create accounts
  • View profiles
  • Publish posts
  • Like posts
  • Follow other users

Everything works perfectly.

The API handles 10,000 requests per day.

Then a famous creator shares the app.

Suddenly, millions of people arrive.

The API receives 10 million requests.

What happens next?

Let's find out.


Step 1: The First Problem Is Usually Not The Server

When developers hear "10 million requests," they often immediately think:

"We need more servers."

Sometimes that's true.

Often, it isn't the first problem.

The first question should be:

Where is the bottleneck?

A request travels through many layers.

User

↓

Load Balancer

↓

Application Server

↓

Database

↓

Cache

↓

External Services
Enter fullscreen mode Exit fullscreen mode

Every layer has limits.

Your API server might handle millions of requests.

But your database might not.

Your database might be fast.

But an external payment API might be slow.

Scaling starts with observation.

Not assumptions.


Step 2: Understanding Request Volume

10 million requests sounds massive.

But let's break it down.

10 million requests per day:

10,000,000 / 86,400 seconds
Enter fullscreen mode Exit fullscreen mode

Approximately:

116 requests per second
Enter fullscreen mode Exit fullscreen mode

That is very different from:

10 million requests per minute.

Numbers matter.

System design is about understanding the actual workload.

Average traffic is important.

Peak traffic is even more important.

A product might average 100 requests per second but experience 5,000 requests per second during a viral event.

Systems usually fail during peaks.

Not averages.


Step 3: The Application Server

Initially, we might have one backend server.

Something like:

User

↓

Django / Node.js / Laravel API

↓

Database
Enter fullscreen mode Exit fullscreen mode

For a small application, this is perfectly fine.

But now thousands of users arrive simultaneously.

The server has limited resources.

CPU.

Memory.

Network connections.

Threads.

Database connections.

Eventually requests begin waiting.

Response times increase.

Users see:

"Loading..."

Then:

"Something went wrong."

The first scaling step is usually horizontal scaling.


Step 4: Horizontal Scaling

Instead of one server, we create many.

             Load Balancer

                  |

       ---------------------

       |         |         |

    API 1      API 2     API 3

                  |

              Database
Enter fullscreen mode Exit fullscreen mode

Now traffic is distributed.

One server no longer carries everything.

The load balancer becomes the traffic controller.

It decides:

"Which server should handle this request?"

This is one of the simplest and most powerful ideas in scalable systems.

Don't make one machine stronger.

Make the system capable of using many machines.


Step 5: The Stateless Principle

Horizontal scaling introduces a new challenge.

Imagine a user logs in.

Server 1 stores their session.

Then the next request goes to Server 2.

Server 2 doesn't know who they are.

The solution is making services stateless.

The server shouldn't remember important information locally.

Instead:

Authentication data goes into tokens.

Sessions go into shared storage.

Files go into object storage.

The database becomes the source of truth.

Stateless systems are easier to scale because every server is interchangeable.


Step 6: The Database Becomes The Real Problem

Eventually, the database becomes the bottleneck.

This happens often.

Applications scale horizontally.

Databases are harder.

Imagine millions of users loading profiles.

Every request does:

SELECT * FROM users WHERE id = ?
Enter fullscreen mode Exit fullscreen mode

The database starts struggling.

Now we need optimization.


Step 7: Database Indexing

The simplest database optimization is often an index.

Without an index:

The database scans every row.

One million users?

Check one million records.

With an index:

The database can quickly find the information.

Like looking up a word in a dictionary.

Indexes are one of the most powerful examples of data structures in real systems.

Behind many database indexes are structures like B-trees.

Computer science becomes practical very quickly.


Step 8: Caching

Now imagine millions of users viewing the same popular profile.

Do we need to ask the database every time?

Probably not.

We introduce caching.

Request

↓

Cache

↓

Database (if missing)
Enter fullscreen mode Exit fullscreen mode

A cache stores frequently requested information.

Examples:

Popular profiles.

Trending posts.

Product information.

Configuration.

Redis is commonly used for this.

But caching introduces new problems.

When does data expire?

What happens when information changes?

How do we avoid stale data?

Caching is powerful because it trades complexity for speed.


Step 9: The Cache Problem

Imagine someone changes their username.

The database updates.

But the cache still has the old value.

Now users see inconsistent information.

This is the famous cache invalidation problem.

One of the hardest problems in computer science is not creating caches.

It's knowing when to remove information from them.

Sometimes the simplest solution is the best.

Cache less.

Expire data quickly.

Only cache expensive operations.


Step 10: Database Replication

Reading data is usually easier than writing data.

So we separate them.

Primary database:

Handles writes.

Replica databases:

Handle reads.

          Application

              |

        --------------

        |            |

     Primary      Replicas

      Write        Read
Enter fullscreen mode Exit fullscreen mode

Now thousands of users can read information without overwhelming the main database.

This pattern appears everywhere.


Step 11: Background Jobs

Another mistake is making users wait for everything.

Imagine creating a post.

The API does:

Save post.

Send notifications.

Generate recommendations.

Resize images.

Update analytics.

Everything happens before responding.

Slow.

Instead:

User Action

↓

Save Data

↓

Queue Job

↓

Process Later
Enter fullscreen mode Exit fullscreen mode

Background workers handle expensive tasks.

The user gets a fast response.

The system stays responsive.


Step 12: Message Queues

Queues become extremely valuable at scale.

A queue absorbs sudden traffic spikes.

Imagine one million notifications need to be sent.

Instead of processing everything immediately:

Application

↓

Message Queue

↓

Workers

↓

Notifications
Enter fullscreen mode Exit fullscreen mode

The system processes work gradually.

Queues create stability.


Step 13: Rate Limiting

At 10 million requests, not every request is necessarily legitimate.

Some users refresh aggressively.

Some clients have bugs.

Some traffic is malicious.

Rate limiting protects the system.

Examples:

100 requests per minute per user.

1000 requests per minute per API key.

Rate limits are not about restricting users.

They're about protecting everyone.


Step 14: Monitoring

At this scale, guessing becomes dangerous.

You need visibility.

Measure:

  • Response time
  • Error rates
  • Database performance
  • CPU usage
  • Memory usage
  • Request volume
  • Queue length

A system you cannot observe is a system you cannot improve.


Step 15: Logging

Logs become your system's memory.

A request fails.

Why?

Logs should tell the story.

User authenticated

Request received

Database query started

Database timeout

Response returned
Enter fullscreen mode Exit fullscreen mode

Good logs turn debugging from detective work into engineering.


Step 16: Designing APIs For Scale

The API itself matters.

Poor API design creates future problems.

Avoid unnecessary data.

Instead of:

GET /users
Enter fullscreen mode Exit fullscreen mode

returning everything:

GET /users?page=1&limit=20
Enter fullscreen mode Exit fullscreen mode

Pagination protects your system.

Good APIs consider future growth.


Step 17: Design Patterns At Scale

Large systems rely on simple design principles.

Repository Pattern:

Separates data access.

Strategy Pattern:

Allows different behaviors.

Observer Pattern:

Supports events.

Factory Pattern:

Controls object creation.

Patterns don't magically make systems scalable.

But they help organize complexity.


Step 18: The Algorithm Behind Scaling

Scaling itself follows an algorithm.

Observe system

↓

Find bottleneck

↓

Improve bottleneck

↓

Measure results

↓

Repeat
Enter fullscreen mode Exit fullscreen mode

There is no magical final architecture.

Every successful system evolves.


Step 19: What About Microservices?

At this point, many engineers immediately say:

"Let's create microservices."

Sometimes that is the right answer.

Sometimes it creates unnecessary problems.

Microservices introduce:

Network communication.

Deployment complexity.

Distributed debugging.

More infrastructure.

The question isn't:

"Can we use microservices?"

The question is:

"Do we have a problem that requires them?"

Architecture should follow reality.

Not trends.


The Bigger Lesson

A system receiving 10 million requests isn't fundamentally different from a system receiving 10,000.

The same principles appear.

Good database design.

Clear APIs.

Efficient algorithms.

Appropriate data structures.

Caching.

Queues.

Monitoring.

Thoughtful architecture.

The difference is that mistakes become more expensive.

At small scale, a bad decision affects hundreds of users.

At large scale, it affects millions.


Why This Matters To Me

One of the reasons I love system design is because it teaches a different way of thinking.

Programming asks:

"How do I make this work?"

System design asks:

"How do I make this continue working when everything changes?"

More users.

More data.

More traffic.

More uncertainty.

Great software isn't built by predicting every possible future.

It's built by creating systems that can adapt.


Final Thoughts

When your API suddenly receives 10 million requests, the solution isn't one technology.

It isn't Kubernetes.

It isn't microservices.

It isn't buying bigger servers.

The solution is understanding your system.

Finding where pressure appears.

Reducing unnecessary work.

Separating responsibilities.

Building for failure.

Measuring everything.

Improving continuously.

The best engineers aren't the ones who build the most complicated architectures.

They're the ones who know exactly how much complexity a problem deserves.

Because at the end of the day, scaling software is not really about handling millions of requests.

It's about building systems that remain trustworthy when millions of people depend on them.




Top comments (0)