Scientyfic World

Serverless Architecture: Benefits, Trade-offs and When to Use It

“Serverless” does not mean there are no servers. It means you don’t provision, patch or scale them: you hand your code (or your data and authentication) to a cloud provider,...

Share:

Get an AI summary of this article

feature image for the blog serverless architecture

“Serverless” does not mean there are no servers. It means you don’t provision, patch or scale them: you hand your code (or your data and authentication) to a cloud provider, which runs it on demand and bills for use. It is a genuinely useful model for some workloads and a poor fit for others. This guide explains what it is, what the real limits are today, how the cost works, and how to decide, with a small working example.

Updated October 2026: I rewrote this 2023 post. The original argued serverless “will become the norm” and listed only benefits, and its examples used an old callback-style Lambda handler. A balanced view is more useful, and the platform has changed: current Lambda runtimes are Node.js 22 and 24 and Python 3.13 and 3.14 (Node.js 20 and 18 are deprecated), and AWS has added newer options such as durable functions. I took limits, runtimes and prices from AWS’s documentation in October 2026 and tested the example handler with a mocked S3 client, but I did not deploy it to a real AWS account.

What Serverless Means

There are two related ideas, and they are often mixed together:

  • Functions as a service (FaaS): you upload a function, and the platform runs it in response to events (an HTTP request, a file upload, a queue message, a schedule). Examples: AWS Lambda, Azure Functions, Google Cloud Functions, Cloudflare Workers.
  • Backend as a service (BaaS) and managed services: databases, authentication, storage and messaging that scale and bill by usage without you running servers, such as DynamoDB, S3 or managed auth.
  • Serverless containers sit in between: you give the platform a container and it scales it (including to zero) without you managing machines, for example Google Cloud Run or AWS Fargate. They relax some function limits at the cost of slower scaling.

The shared traits: no server management, automatic scaling, and (for most services) pay-per-use pricing with little or nothing charged when idle.

How It Differs From Server-Based Architecture

Servers (VMs, containers you run)Serverless
Who manages the machinesYou: OS patches, capacity, scalingThe provider
ScalingYou configure it, and it takes minutes to add capacityAutomatic and per request, within quotas
Cost when idleYou pay for running capacityNear zero for FaaS
Cost at steady high loadOften cheaper per requestCan become more expensive than always-on servers
Execution limitsFew: long jobs, big memory, persistent connections are fineReal limits on duration, memory, payload size and state
StateCan keep state in memory or on diskFunctions are stateless; state lives in external services
PortabilityStandard containers move between cloudsEvent formats and managed services tie you to a provider

What Lambda Actually Limits (October 2026)

Limits decide whether serverless fits your workload. From AWS’s Lambda quotas page:

  • Duration: up to 15 minutes per invocation (900 seconds). Longer jobs need a different tool, such as a container service, a batch service, or Lambda’s newer durable functions or Managed Instances options, which have higher limits for specific cases.
  • Memory: 128 MB to 10,240 MB, and CPU scales with memory (1,769 MB gives the equivalent of one vCPU). There is no separate CPU setting, so a CPU-heavy function needs more memory.
  • Payload: 6 MB each for request and response on synchronous invocations (200 MB for streamed responses), and 1 MB for asynchronous ones. Large files go through S3, not through the function.
  • Concurrency: 1,000 concurrent executions per Region by default, across all functions, and new accounts start with reduced quotas that AWS raises with usage. Each function can add 1,000 execution environments every 10 seconds. The account’s request rate is also capped at 10 times its concurrency.
  • Package size: 50 MB zipped (250 MB unzipped), or up to 10 GB as a container image.
  • Temporary storage: /tmp from 512 MB to 10,240 MB. Nothing persists between environments.

Runtimes. Per AWS’s runtimes page, managed runtimes include nodejs22.x and nodejs24.x, python3.13 and python3.14, Java 21 and 25, .NET 10 and Ruby 3.4 and 4.0, with Go and Rust through OS-only runtimes. AWS deprecates runtimes when the language version reaches end of life: Node.js 18 and Node.js 20 are already deprecated, and Python 3.10 is scheduled for deprecation on 31 October 2026. After deprecation AWS may stop patching the runtime and you are responsible for upgrading, so serverless does not mean maintenance-free; it means a different maintenance task.

How the Cost Works

Lambda pricing has two main meters: $0.20 per million requests, and $0.0000166667 per GB-second of duration on x86 (Arm is cheaper). A perpetual free tier gives 1 million requests and 400,000 GB-seconds a month. Duration includes code that runs outside the handler during initialisation. Extras such as provisioned concurrency and SnapStart are billed separately.

A worked example: a function configured with 512 MB (0.5 GB) that runs 200 ms per call uses 0.1 GB-seconds per call. A million calls a month is 100,000 GB-seconds, which sits inside the free allowance, so the compute is free and you’d pay roughly nothing beyond the request charge (and even that is covered up to a million). Multiply by 100 and you have 100 million calls and 10 million GB-seconds: about $20 for requests plus roughly $160 for duration after the free tier (before API gateway and data transfer costs). At that point, compare with a small always-on service; steady, high-volume traffic is where servers often win on cost.

Don’t forget the surrounding services: an API gateway in front of the function, logs, data transfer, and the database all have their own meters, and often dominate the bill.

The Real Benefits

  • No idle cost and scale-to-zero. Ideal for spiky or unpredictable traffic, internal tools, cron jobs and glue code.
  • Automatic scaling from zero to the quota without capacity planning, which suits event-driven work such as processing uploads.
  • Less infrastructure to run. No OS patching or server fleet; the provider handles the underlying hosts.
  • Fast to start. A small team can ship an API or pipeline without building a platform.
  • Built-in integrations. Events from storage, queues, schedules and HTTP are wired up through configuration.

About the old post’s claim of “improved security”: the provider secures the host and runtime, but under the shared-responsibility model you still own your code, its dependencies, its permissions (over-broad IAM roles are the classic mistake), your secrets and your data. Serverless changes the attack surface; it doesn’t remove it.

The Real Trade-Offs

  • Cold starts. When there is no ready execution environment, Lambda must initialise one first, adding latency to that request. Per AWS’s concurrency documentation, you can pre-initialise environments with provisioned concurrency (extra cost) or, for supported runtimes, use SnapStart. Keep initialisation light, reuse clients created outside the handler, and measure real latency before worrying.
  • Limits. Long jobs, large payloads, big in-memory datasets and persistent connections (such as WebSockets held by your own code) don’t fit well.
  • Debugging and observability. Distributed, event-driven systems are harder to trace and test locally than one application. Invest in structured logging, tracing and alarms early.
  • Vendor coupling. Your code can be portable but your event sources, permissions and managed services usually aren’t. Decide how much lock-in you accept; frameworks and container-based options reduce but don’t remove it.
  • Cost surprises. Pay-per-use cuts both ways: a bug that loops, a retry storm, or a public endpoint hit by bots can run up a bill. Set budgets, alarms, concurrency limits and API throttles.
  • Downstream limits. Lambda can scale faster than your database. Cap concurrency or use a queue so a spike doesn’t overwhelm a relational database’s connection limit.

A Working Example: Thumbnails on Upload

The original post compared an Express server with a Lambda that resized images. Here is a current version of the serverless half: a Node.js function that runs when an image lands in one S3 bucket and writes a 320-pixel-wide WebP thumbnail to a different bucket. Using a separate output bucket matters: writing results back into the bucket that triggers the function creates an infinite loop (and a very large bill).

import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
import sharp from 'sharp';

// Created once per execution environment and reused across invocations (warm starts)
export const s3 = new S3Client({});

const OUTPUT_BUCKET = process.env.OUTPUT_BUCKET;   // a DIFFERENT bucket, so our own output can't trigger us again
const WIDTH = Number(process.env.THUMB_WIDTH || 320);

export const handler = async (event) => {
  const results = [];
  for (const record of event.Records ?? []) {
    const bucket = record.s3.bucket.name;
    // S3 URL-encodes object keys in events: spaces arrive as "+"
    const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, ' '));
    if (!/\.(jpe?g|png|webp)$/i.test(key)) continue;

    const original = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
    const input = Buffer.from(await original.Body.transformToByteArray());

    const thumbnail = await sharp(input)
      .rotate()                                   // honour EXIF orientation
      .resize({ width: WIDTH, withoutEnlargement: true })
      .webp({ quality: 80 })
      .toBuffer();

    const outKey = key.replace(/\.[^.]+$/, '') + '-thumb.webp';
    await s3.send(new PutObjectCommand({
      Bucket: OUTPUT_BUCKET, Key: outKey, Body: thumbnail, ContentType: 'image/webp',
    }));
    results.push({ key, outKey, bytes: thumbnail.length });
  }
  return results;
};

I ran this handler against a mocked S3 client with a generated 2000×1500 JPEG: it fetched the original, produced a 320×240 WebP and wrote it to the output bucket under the right key, and it skipped a PDF. I did not deploy it. Points worth noting:

  • The client is created outside the handler, so warm invocations reuse it (initialisation code runs once per environment, though it is billed as part of duration).
  • Keys are decoded. S3 URL-encodes object keys in event notifications and turns spaces into “+”.
  • Native dependency. The image library sharp includes native binaries, so install it for the Lambda platform, as its documentation describes: npm install --os=linux --cpu=x64 sharp for x86 or --cpu=arm64 for Arm, matching your function’s architecture. It requires Node.js 20.9 or later (use the Node.js 22 or 24 runtime). Give the function enough memory, since image work is CPU-bound and CPU scales with memory.
  • Configuration: set the OUTPUT_BUCKET environment variable, grant the function’s role s3:GetObject on the source bucket and s3:PutObject on the output bucket only, and configure an S3 object created event notification to invoke the function (limit it by prefix or suffix).
  • Errors and retries. S3 invokes functions asynchronously and retries failures, so make the handler idempotent (re-running it overwrites the same output key, which is safe) and configure a dead-letter queue or failure destination for images that keep failing.

The server-based equivalent keeps a process running to receive uploads and resize images, which is simpler to reason about for a steady stream of uploads and cheaper at very high volume, but it means you handle scaling, patching and idle capacity. For occasional or bursty uploads, the function wins; for constant heavy traffic, price both.

When to Use Serverless, and When Not To

Good fitPoor fit
Event processing: uploads, queue messages, webhooks, streamsLong-running jobs beyond the duration limit
Spiky or unpredictable HTTP APIs and low-traffic appsSteady, very high-volume traffic where always-on capacity is cheaper
Scheduled jobs, automation and glue between servicesLatency-critical paths that can’t tolerate any cold start
Prototypes and small teams that want little ops workWorkloads needing GPUs, huge memory or persistent connections
Edge logic, such as redirects, auth checks and A/B testsSystems where portability across clouds is a hard requirement

A sensible middle path for many teams: use serverless for event-driven and spiky pieces, and containers or VMs for steady core services. Related reading: what is Model Context Protocol (a common thing to host as a small remote service) and running n8n on a small cloud VM for the server-based alternative.

Does serverless mean there are no servers?

No. There are servers, but the provider manages them. You don’t provision, patch or scale machines; you deploy code or use managed services and pay for usage.

What are the main limits of AWS Lambda?

Per AWS’s quotas: 15 minutes maximum per invocation, 128 MB to 10,240 MB of memory, 6 MB request and response payloads for synchronous calls, 1,000 concurrent executions per Region by default (reduced for new accounts), and 50 MB zipped or 10 GB container image packages.

Is serverless cheaper than servers?

It is usually cheaper for spiky, low or unpredictable traffic because you pay nothing when idle. For steady high volume, always-on servers can be cheaper per request. Include surrounding services such as API gateways, logs and data transfer when you compare.

What is a cold start?

When a function is invoked and no initialised execution environment is available, the platform must create one first, which adds latency to that request. Mitigations include lighter initialisation, provisioned concurrency (extra cost) and SnapStart for supported runtimes.

Is serverless more secure?

It removes host and OS patching from your list, but you still own your code, dependencies, permissions, secrets and data. Over-broad permissions and vulnerable dependencies remain the common problems, so apply least privilege and keep dependencies updated.

Snehasish Konger
Developed @scientyficworld.org | Technical writer @Nected | Content Developer
Connect with Snehasish Konger

On This page

Take a Pause with Intervals

A Sunday letter on building, writing, and thinking deeper as a developer — short, honest, and worth your time.

Snehasish Konger profile photo

"Hey there — I'm Snehasish. Hope this post saved you some head-scratching time! I've spent years turning technical chaos into clarity, and I'm here to be your guide through the maze of modern tech. Stick around for more lightbulb moments — we're just getting started."

Related Posts