Serverless or containers for a startup backend? How we decide
We run both: Lambda and DynamoDB for some clients, Rails and Django on containers for others. The questions that actually decide it, and the ones that don't.
We maintain backends on both sides of this argument. Two of our current products run entirely on AWS Lambda and API Gateway, deployed with CDK: one on DynamoDB, one on RDS MySQL. Others are Rails or Django monoliths in containers on AWS. None of them is wrong, and none of them was chosen by reading a benchmark. Here are the questions that actually decided it.
The questions that don’t decide it
Cost at scale. Founders worry about the Lambda bill at a million requests a day. By the time you have that problem you have the revenue to rewrite the hot path, and you’ll know exactly which path is hot. Early on, both options cost less than one engineer-hour a month.
Cold starts. Real, and mostly solved. A Python Lambda behind API Gateway cold-starts in a few hundred milliseconds; with provisioned concurrency on the two or three endpoints users notice, it’s not a factor. If your product is a trading terminal, this matters. If it’s a booking app, it doesn’t.
“Serverless doesn’t scale” or “containers don’t scale”. Both scale further than a startup backend will need to for years. What differs is how they fail when something unexpected happens, which is the next section.
The questions that do
1. What shape is your traffic?
A commute-tracking platform we run has traffic that arrives in two sharp peaks a day, when people log their trips, and near silence overnight. Paying for idle containers to cover the peaks would be waste, and the serverless model fits exactly: scale to zero, scale to the peak, no capacity planning.
A dental analytics product with hundreds of practices has steady traffic through the working day, background jobs on a schedule, and reporting queries that run for seconds, not milliseconds. A long-running Rails process with a connection pool and a job queue is the natural shape for that, and we run it in containers.
If you can’t describe your traffic shape yet, that’s an answer too: start serverless, because being wrong about capacity costs nothing.
2. Is your data relational, and how relational?
This is the question most teams underweight. Serverless pairs naturally with DynamoDB, and DynamoDB makes you decide your access patterns up front. For the commute platform that was fine: trips, rollups per user, per site and per organisation, settlement records. We modelled eighteen tables around known queries and never needed a join.
A marketplace with orders, line items, sellers, warehouses, shipping rules and payouts is relational to its core. Reporting on it means joins and aggregates that someone will want to change next week. That product runs on PostgreSQL behind Django, and it should. You can run Lambda against a relational database, and one of our serverless backends does exactly that with RDS MySQL, but you pay in connection management and you lose some of the scale-to-zero story.
3. What does your team already know?
A team fluent in Rails will ship faster on Rails in a container than on a Lambda architecture they’re learning, and speed of shipping is the whole game in the first year. The reverse is also true. We’ll recommend the thing the people maintaining it can debug at 2 a.m., not the thing with the better conference talk.
4. How long does your work take?
Request handlers are short. But products have long work: a report that reads six months of data, a payout job that calls a payment provider for every seller, an export that builds a hashed audit package. Lambda has a fifteen-minute ceiling and makes you think about retries and partial progress. Sometimes that discipline is welcome: our audit export is a self-invoking Lambda that checks its reconciliation before producing anything, and the time limit forced a design that fails safely. Sometimes it’s just friction, and a worker process in a container is the honest answer.
5. How do you want to run it locally?
Containers give you a laptop that runs the same thing production runs. Serverless gives you a laptop that runs an approximation, with real behaviour only in a deployed stage. We mitigate that with a dev stage per developer and fast CDK deploys, and it works, but it’s a real cost for a team that likes to step through code.
6. What has to be auditable?
Serverless gives you a per-function, per-invocation record for free, which auditors like. Containers give you one process to put the right logging in. Both can be made compliant; one of our containerised products holds SOC 2 and HIPAA obligations and one of the serverless ones handles children’s data under COPPA. The difference is where you spend the effort, not whether you can.
What we’d pick, by product
| Product | Our usual pick | Why |
|---|---|---|
| Booking, scheduling, notifications | Serverless | Spiky traffic, event-driven work, scheduled jobs map directly to EventBridge |
| Marketplace with orders and payouts | Containers + PostgreSQL | Relational data, reporting, long-running settlement |
| Analytics SaaS over customer data | Containers + PostgreSQL (+ search index) | Steady load, heavy queries, background sync |
| Internal tools and dashboards | Either; whatever the team knows | Low traffic, speed of change matters most |
| Anything handling webhooks from Stripe, Twilio, etc. | Serverless for the webhook edge | Idempotent, bursty, isolated from the main app |
The last row is the hybrid we end up with most often: a container for the application and a handful of functions at the edges for webhooks, scheduled jobs and exports. It is not a compromise. It’s using each for the shape of work it’s good at.
The decision in one paragraph
If your traffic is spiky, your data fits known access patterns, and your team is comfortable deploying to a cloud stage to test, go serverless and keep the architecture simple. If your product is relational at its core, runs long jobs, or your team ships faster in a framework they know, run containers and add functions at the edges. Either way, write the infrastructure as code from day one, because the choice you make now is easier to change than the habit of clicking around a console.
If you’re weighing this for a product you’re about to build, tell us about it. We’ll give you a straight recommendation, including the one where you don’t need us.