A team built its new service on AWS Lambda with a “serverless first” decision. Yet the traffic was steady and predictable — roughly the same all day. At the end of the month the bill came in at several times what a single VPS doing the same work would cost; on top of that, p95 latency was worse.

Serverless isn’t the wrong technology. It was the right technology applied to the wrong workload.

What serverless buys you

FaaS (Function as a Service) has real upsides:

  • No server management. Patching, scaling, capacity planning all sit with the provider.
  • Scale to zero. No requests means nothing running and nothing paid for.
  • Pay per use. You don’t pay for idle capacity.

These three genuinely pay off on the right workload. The trick is diagnosing that workload correctly.

The real cost of cold-start

If a function hasn’t been called for a while, the provider brings it up from scratch: the runtime loads, dependencies initialize, the code runs. This cold-start adds anywhere from hundreds of milliseconds to seconds of latency compared to an already-running process.

The key distinction: for a low-traffic endpoint, cold-start is the rule, not the exception. On a function that gets a few calls an hour, nearly every request is cold. “Pay by scale” sounds appealing, but at near-zero traffic what you pay is the latency the user sees every single time. On a latency-sensitive user path, that’s a direct UX cost.

Vendor lock-in

Lock-in isn’t just the runtime; the real bond is in the glue around it. Over time a serverless application also couples to the provider’s event sources, identity/authorization model (IAM), managed queue, API gateway, and deployment tooling.

Moving a single function is easy. But in a real system, “getting off serverless” is usually not a migration, it’s a rewrite. This ties directly into the innovation-token logic from the boring architecture piece: what looks like a single decision is actually a bond that’s expensive to undo.

Which workloads win

Serverless shines where the load is variable and sparse:

  • Scheduled jobs — nightly reports, cron-like tasks.
  • Webhook receivers — uncertain when and how often they’ll arrive.
  • Low-volume internal tools — panels used a few times a day.
  • Bursty batch jobs — once an hour, briefly high parallelism.

On these workloads, scale-to-zero is real money saved, and cold-start is usually irrelevant — nobody cares that a nightly report starts 800 ms late.

Which workloads lose

The reverse is just as clear:

  • Steady, continuous traffic. On an always-running API, “pay per use” turns into “pay every second” — and that’s usually more expensive than a continuously running server.
  • Latency-sensitive paths. Cold-start is unacceptable on a request the user is waiting on.
  • Long-running jobs. FaaS has execution-time limits; long jobs either get split up or don’t fit.

For a workload with this profile, a boring VPS — like the setup in the multiple projects on a single VPS piece — is both cheaper and more predictable. The cost of a steady load matches a steady server.

Laravel and serverless

On the Laravel side, Laravel Vapor makes it possible to run the application on Lambda, and it works well. But that it works doesn’t mean it’s the right decision: with Vapor you also inherit cold-start and the AWS bond.

The decision is, again, the workload. For a Laravel app with bursty, sparse, or unpredictable traffic, Vapor makes sense. For a continuous, latency-sensitive app, a classic server is still the plainer, cheaper answer.

Mix them

This isn’t a binary choice. A boring server carrying the continuous load + handing only the sparse/bursty work (webhooks, the nightly report) to serverless is often the most honest split. Put every workload where its own cost profile belongs.


Serverless isn’t an architectural fashion, it’s a tool for a specific workload profile. If you have that profile, it pays off; if you don’t, it’s paid back as cold-start and lock-in.

Measure your load first; the tool comes after.