AWS Builder Center

My Serverless App Crashed at 100 Users – And It Wasn’t the Code’s Fault

A forgotten Lambda reserved concurrency setting took down our college fest registration within seconds of launch. How I found the real problem, the debugging mistake I almost made, and why serverless still demands operational thinking.

Two weeks ago I thought I had serverless completely figured out.
I’d built an event-registration API for our college fest. API Gateway, Lambda, DynamoDB. Clean, minimal, fully “cloud-native.” My friends tested it. I tested it. Three concurrent registrations? Flawless. I even tweeted a tiny fire emoji next to the words “production ready.”
Then we opened registrations at 8 p.m.
Within 90 seconds, everything went quiet. No error emails from my code. Just silence—and a flood of WhatsApp messages from the fest team: “Link not opening”, “502 Bad Gateway”, “Bro did you even turn it on?”
I opened the AWS console with that specific type of panic where your fingers move faster than your brain. My first instinct was, embarrassingly, IAM. I started checking the Lambda execution role, convinced I’d somehow locked the function out of its own logs. I wasted twenty minutes chasing a permission ghost. I only stopped when I noticed the CloudWatch log stream had… no new entries. None. A healthy function should at least say it failed.
The problem wasn’t permissions. The problem was concurrency.
Lambda’s reserved concurrency was set to 10. I’d set it weeks ago while learning about cost controls and completely forgotten. That harmless number meant only 10 request-invocations could run at the same time. The 11th person, the 50th person, the 200th person—they didn’t even touch my code. AWS dropped them silently before the function started. No log, no trace, just a generic 502 from API Gateway.
I sat there staring at the “Throttle” graph with a spike like a middle finger. I’d imagined serverless as an elastic, infinitely scalable magic carpet. It turned out the carpet had a small “maximum occupancy” sticker I’d placed myself.
The fix took less than two minutes: bump the reserved concurrency to something sensible, add a modest provisioned concurrency for cold starts, and wrap the frontend fetch call in a tiny exponential backoff so a retry didn’t make things worse. We reopened registrations at 8:45 p.m. and 400 people signed up without a single hiccup.
But the real lesson was slower to sink in.
Serverless doesn’t absolve you from thinking about limits. It just changes the knobs you turn. Earlier in this blog I learned the hard way that AWS isn’t about memorising services. This time I learned that even elastic services have a throttle pedal, and the person driving is still you. The cloud gives you powerful defaults, but it won’t stop you from under-provisioning your own function—or forgetting you ever touched that setting.
The other lesson? One curl loop isn’t a load test. If I’d taken ten minutes to fire 100 concurrent requests before going live, I would have caught the concurrency cap in a safe, dignified environment, not with a thousand impatient students refreshing the link.
I still like serverless. I’ll use it again. But now I have a small ritual before any public launch: I go into the Lambda console and say out loud, “Have I accidentally set a concurrency limit that will ruin my evening?” It’s not a magic fix. But it stops me from chasing IAM errors that don’t exist.
The takeaway I keep re-learning on this blog: understanding how something fails is more valuable than knowing how it works in perfect conditions. And sometimes, the failure isn’t in your code at all—it’s in a single number you typed three weeks ago and forgot.
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article