Scalability for Dummies - Part 4: Asynchronism
By Oleksandr Andrushchenko — Published on — Modified on
In Scalability for Dummies - Part 3: Cache, we reduced database load by avoiding unnecessary queries.
But even after adding clones, optimizing the database, and introducing caching, some requests are still slow.
Why?
Because the user is waiting for work that does not need to happen right now.
Table of Contents
- The Problem
- What Is Asynchronism?
- Common Use Cases
- Queues and Workers
- Architecture Example
- Common Mistakes
- Conclusion
The Problem
Imagine a user uploads a profile picture.
The system needs to:
- Store the file
- Generate thumbnails
- Compress the image
- Update the database
- Send notifications
Should the user wait for all of that?
Probably not.
The user only cares that the upload was accepted.
Everything else can happen later.
Why Users Wait
Many applications accidentally perform too much work during the request itself.
User Request
│
▼
Database Update
│
▼
Send Email
│
▼
Generate PDF
│
▼
Call Third-Party API
│
▼
Return Response
The response becomes slower because every step must finish before the user receives an answer.
Urgent vs Non-Urgent Work
A useful question is:
Does the user need the result right now?
If the answer is no, that work is usually a candidate for asynchronous processing.
| Operation | Synchronous? |
|---|---|
| Login validation | Yes |
| Payment authorization | Usually yes |
| Sending email | No |
| Thumbnail generation | No |
| Analytics events | No |
| Push notifications | No |
What Is Asynchronism?
Asynchronism means accepting work now and completing it later.
Instead of making the user wait, the application records a task and returns immediately.
User Request
│
▼
Create Task
│
▼
Return Response
Worker Processes Task Later
This dramatically improves perceived performance because users stop waiting for background work.
Real-World Analogy
Imagine ordering furniture online.
The website does not build the furniture while you wait.
It accepts the order, gives you confirmation, and schedules the work.
Asynchronous systems work the same way.
Queues and Workers
The most common implementation uses queues and workers.
User
│
▼
API
│
▼
Queue
│
▼
Workers
The API remains fast because workers perform the expensive tasks separately.
If traffic doubles, you can add more workers without changing the API layer.
Scaling Workers
Suppose one worker processes 100 emails per minute.
Ten workers can process roughly 1,000 emails per minute.
This is the same scaling pattern we used with clones earlier in the series.
Architecture Example
User
│
▼
API Clones
│
▼
Redis / SQS / RabbitMQ
│
▼
Worker Clones
│
├── Send Emails
├── Generate PDFs
├── Resize Images
└── Process Notifications
Notice that the user no longer waits for those tasks to complete.
Common Mistakes
Making Everything Async
Not every operation should be asynchronous.
If the user needs the result immediately, keep it synchronous.
Ignoring Retries
Workers fail.
Networks fail.
External APIs fail.
Background jobs should usually be retryable.
Ignoring Idempotency
A job may run twice.
Your system should produce the same result if that happens.
Conclusion
Asynchronism improves scalability by removing expensive work from the request path.
Instead of making users wait, systems accept work immediately and process it in the background.
This reduces latency, improves throughput, and allows workloads to scale independently.
If the user does not need the result right now, consider making it asynchronous.
In the next part of the series, we will explore another common scalability technique: batching and aggregation.
Comments (0)