š Why Async ā Scalable
Non-blocking code can still melt your system
Async removes waiting.
Scalability removes limits.
They are not the same thing.
1ļøā£ The Popular Myth
āWe made everything async ā now it scales.ā
Async helps a single thread do more work.
Scalability is about how much total work the system can safely handle.
You can have:
Fully async code
Zero locks
No blocking
ā¦and still go down under load.
2ļøā£ What Async Actually Solves
Async helps when:
Threads are waiting on I/O
Latency is dominated by network
Concurrency is moderate
Async does NOT:
Increase CPU
Increase DB capacity
Remove hot keys
Fix amplification
Failure Mode #1 ā Async Fanout Explosion
ā Naive Async Code
async function getFeed() {
const posts = await db.getPosts();
return Promise.all(
posts.map(p => fetchComments(p.id)) // async ā cheap
);
}
What Happens
1 request ā N async calls
N sockets
N callbacks
N failure chances
Async just made amplification faster.
Failure Mode #2 ā Async Still Queues (Hidden)
Async systems still queue ā just not where you expect.
Where queues exist:
Event loop
Thread pool
Connection pool
OS scheduler
ā Async without limits
app.get("/data", async (req, res) => {
res.send(await db.fetch());
});
If traffic > DB capacity:
Promises pile up
Memory spikes
Latency explodes
Failure Mode #3 ā Async Amplifies Tail Latency
Async increases concurrency, which:
Increases contention
Increases variance
Increases P99
Async improves P50 and worsens P99 unless controlled.
Failure Mode #4 ā Async Makes Failure Faster
ā Fast Failure Propagation
Promise.all([
serviceA(),
serviceB(),
serviceC()
]);
One slow service ā whole request waits
One failing service ā retries explode
Async accelerates cascading failures.
ā What Actually Makes Systems Scalable
Scalability requires explicit limits
| Requirement | Needed |
|---|---|
| CPU safety | Concurrency caps |
| DB safety | Connection limits |
| Latency | Timeouts |
| Stability | Backpressure |
| Survival | Load shedding |
Async alone gives none of these.
Async + Limits = Scalable
ā Correct Pattern
import pLimit from "p-limit";
const limit = pLimit(100);
app.get("/data", async (req, res) => {
try {
const result = await limit(() => fetchWithTimeout(200));
res.send(result);
} catch {
res.status(503).send("Busy");
}
});
This adds:
Concurrency control
Timeouts
Load shedding
Now it scales.
Async vs Scalable (Clear Comparison)
| Property | Async | Scalable |
|---|---|---|
| Non-blocking | ā | Optional |
| Concurrency | High | Controlled |
| Backpressure | ā | ā |
| Load shedding | ā | ā |
| P99 safety | ā | ā |
