Why I put Krabber on Elastic Beanstalk, not Lambda

// written in 2022: tools, versions and prices may have changed since.

Part of my Krabber series, a Twitter clone in Go. The full source is on GitHub.

Intro

When you build a small web app in 2026, the reflex answer is “throw it on Lambda.” Serverless, scale to zero, pay per request. And for a lot of things that’s the right call. But when I shipped Krabber, my Twitter clone, I put it on a single Elastic Beanstalk instance instead, and I want to walk through why, because the reasoning is the interesting part, not the YAML.

I. The decision

Krabber runs on one t4g.micro Beanstalk instance with CloudFront in front of it for HTTPS. That’s it. One box, one CDN, one DynamoDB table behind it.

I’ll move to Lambda eventually (more on that at the end), so this isn’t a “serverless bad” post. It’s a “right tool for launch day” post. Here’s what tipped it.

II. Why not Lambda (yet)

Four reasons, roughly in order of how much they mattered.

First, the cost is fixed. An instance costs the same whether it’s idle or getting hammered. With CloudFront’s flat-rate plan in front and the box only accepting traffic from CloudFront, an attack can make the site slow but it can’t grow the bill. On Lambda, every request that reaches a function URL is billed, even the ones you reject, so you have to bolt on a kill switch and per-function concurrency caps just to keep a bad day from becoming a bad invoice. I pay for Krabber myself, so a known ceiling beat a few dollars of savings.

Second, there was almost no rewrite. Krabber was already a long-running HTTP server listening on a port, with a Procfile and background goroutines, the sea-refresh ticker and the Trench fan-out worker, all living in one process. Beanstalk runs exactly that, as is. Lambda would have meant splitting those background jobs out into their own functions and event triggers before I could even launch.

Third, I wanted to launch in about a day, not a week. My AWS account’s Lambda concurrency quota is 10, which is too low to safely reserve concurrency per function until AWS raises it. Beanstalk had none of that friction.

And fourth, I was honest about the costs of the choice. Beanstalk runs me about $8–10 a month more than Lambda would at hobby traffic, and one instance is a single point of failure. I decided that was a fine trade for launch, and I can pay it down later.

III. Why Amazon Linux, and the SSH-free bonus

Beanstalk lets you pick the platform image, and I run the Amazon Linux 2023 Go platform. That choice quietly bought me something I use all the time.

The instance has no EC2 key pair, no port 22 open, and IMDSv1 turned off. I get on the box with AWS Systems Manager Session Manager instead of SSH, and that works out of the box specifically because Amazon Linux ships the SSM agent preinstalled. On a lot of other images you’d be installing and wiring up the agent yourself before Session Manager would even connect.

I think this is better than storing SSH keys, and not just a little. There’s no private key sitting on my laptop to leak, nothing listening on 22 for the internet to poke at, and every session is logged through SSM with normal IAM permissions. When the site went down and I needed to poke at the box, I just ran aws ssm start-session --target <instance-id> and I was on. No key, no bastion, no fuss.

IV. Lambda is still the plan, just later

None of this is me swearing off serverless. Krabber was built stateless on purpose, sessions live in DynamoDB, config comes from SSM, and background jobs can resume from markers in the table, so moving to Lambda later is a deployment change, not a rewrite. The plan is CloudFront in front of Lambda function URLs, the background jobs split into their own functions on DynamoDB Streams and EventBridge, and reserved concurrency as a hard cost cap. That version runs more like $1–3 a month.

I just didn’t need it on day one, and reaching for it on day one would have slowed me down and added moving parts for savings I don’t feel at this size.

Conclusion

The lesson I keep relearning is that “what’s trendy” and “what’s right for this moment” aren’t always the same answer. Beanstalk let me launch fast, on code I already had, with a bill I can’t accidentally blow up, and the platform choice threw in SSH-free access as a bonus. Lambda is the right next step, and it’ll be there when the traffic or my patience asks for it. If you’re sitting on a long-running app and feeling guilty for not going serverless, don’t. Pick the thing that gets you shipped. Thanks for reading, and may your instances stay cheap.

cd ../blog