Cloud

Serverless architecture: the trade-offs nobody mentions in the demo

Serverless removes operational work and introduces different constraints. Knowing them in advance is the difference between a good fit and a rewrite.

Key takeaways

  • Serverless removes operational work and constrains execution.
  • Cold starts matter for user-facing latency-sensitive paths.
  • Cheap at spiky volume; often expensive at sustained high volume.
  • Mixing serverless and containers in one system is normal.

What you genuinely gain

No servers to patch, automatic scaling to zero and to peak, and a cost model that charges for use rather than for capacity. For bursty, event-driven workloads that is a substantial advantage.

It also removes an entire category of operational work, which matters most for small teams with no dedicated platform capability.

The constraints that bite

  • Execution limits — maximum duration, memory and payload sizes constrain what a function can do.
  • Cold starts — noticeable for latency-sensitive user-facing paths, particularly on heavier runtimes.
  • Local development — harder to reproduce faithfully than a container.
  • Debugging — distributed tracing becomes essential rather than optional.

Cost is not automatically lower

Serverless is very cheap at low and spiky volume and can become expensive at sustained high volume, where reserved capacity on containers is cheaper per unit of work.

Model the cost at your expected steady-state volume, not just at launch volume. The crossover point is real and worth knowing before you build.

Where it fits best

Event processing, scheduled jobs, webhook handlers, image and document processing, and glue between managed services — all excellent fits.

Long-running processes, workloads needing large in-memory state, and consistently high-throughput services are usually better served by containers. Mixing both in one system is normal and sensible.

Observability in a serverless estate

Debugging serverless systems is harder because there is no long-lived process to inspect. Investigation depends entirely on the telemetry you emitted at the time, which means instrumentation cannot be an afterthought.

Use structured logging with a correlation identifier propagated through every invocation, and distributed tracing across function boundaries and managed services. Without tracing, a slow request in a chain of six functions is genuinely difficult to attribute.

Set alerts on error rates, throttling and dead letter queue depth. Throttling in particular is easy to miss and produces symptoms that look like application failures.


Frequently asked questions

Choose a lighter runtime, keep deployment packages small, and use provisioned concurrency for the specific paths where latency matters. Not every function needs it.

Parts of it, usually. A common pattern is serverless for asynchronous processing and integrations, with containers for the main request-serving API.

Keep business logic in plain functions with no dependency on the platform's event shape, test those normally, and keep the handler as a thin adapter. This makes the majority of the code testable without emulation.

Working on this?

A conversation with our team, no charge and no obligation.

Book a conversation