Serverless Architecture
Event-triggered managed compute where the cloud provider handles provisioning, scaling, and operations. You write functions; the platform runs them on demand.
What it is
Serverless architecture is a cloud-execution model where code is deployed as individual functions that execute in response to events (HTTP requests, queue messages, scheduled triggers, file uploads). Function-as-a-Service (FaaS) — AWS Lambda, Google Cloud Functions, Azure Functions — is the compute primitive: each function invocation is independently isolated, stateless, and billed by duration and memory used (not uptime). Backend-as-a-Service (BaaS) extends the model to managed services for storage, authentication, and databases (DynamoDB, Firebase, Auth0) that eliminate the need to manage backend servers entirely. The cloud provider allocates compute capacity automatically, scales to zero when idle, and scales to thousands of concurrent invocations under load — with no capacity planning required from the developer.
Why it exists
Traditional servers (and to a lesser extent containers) require paying for compute capacity even when idle. Intermittent or spiky workloads — nightly batch jobs, image thumbnailing, webhook processors, scheduled reports — pay for 24/7 compute to handle peak load that may last only minutes. Serverless eliminates this waste by billing only for actual execution time (often measured in milliseconds). It also removes the operational overhead of patching OS, managing runtime versions, configuring auto-scaling groups, and handling infrastructure failures. For small teams and early-stage products, this dramatically reduces the cost and complexity of running production software. Serverless also naturally aligns with event-driven decomposition — each event type maps to a focused function with a single responsibility.
When to use
- Intermittent, spiky, or unpredictable workloads where paying for idle capacity is wasteful.
- Event-driven pipelines: image/video processing triggered by uploads, ETL transformations, webhook handlers.
- Scheduled jobs (cron-style triggers): nightly reports, data cleanup, status checks.
- Microservices with very low traffic that don't warrant a persistent container process.
- API backends where per-request billing and managed scaling are preferable to reserved capacity.
When not to use
- Long-running compute tasks — FaaS execution limits (15 minutes on Lambda) preclude use for jobs requiring sustained computation.
- Latency-sensitive paths where cold start delay (10ms–1s+ for JVM runtimes) is unacceptable.
- High-throughput, consistently loaded workloads — at high invocation rates, reserved containers are cheaper than per-invocation billing.
- Scenarios requiring shared mutable in-process state between invocations — functions are stateless by design.
Typical architecture
Events from multiple sources trigger functions. Functions are stateless and invoke managed services for persistence. Orchestrators coordinate multi-step workflows.
HTTP API ─────────────▶┌──────────────────────┐
S3 Upload ────────────▶│ FaaS Functions │
SQS Queue ────────────▶│ (Lambda / Cloud Fn) │
EventBridge ──────────▶│ - Stateless │
Scheduler ────────────▶│ - Ephemeral │
└──────────┬───────────┘
│
┌───────────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌─────────────▼────┐ ┌────────▼────────┐
│ DynamoDB │ │ S3 / Storage │ │ Step Functions │
│ (State) │ │ (Files/Output) │ │ (Orchestration) │
└─────────────┘ └──────────────────┘ └─────────────────┘
Pros and cons
Pros
- Zero infrastructure management — no OS patching, no capacity planning, no scaling configuration.
- Pay-per-invocation billing: idle functions cost nothing.
- Automatic scaling from zero to massive concurrency in response to demand.
- Rapid deployment — functions deploy in seconds with no cluster management.
- Built-in high availability through cloud provider infrastructure.
Cons
- Cold starts: new function instances take 10ms–2s+ to initialize (JVM runtimes worst); unacceptable for latency-sensitive user-facing endpoints.
- Vendor lock-in: Lambda invocation model, IAM, step functions, and event source mappings are proprietary.
- Execution limits: max 15 minutes (Lambda), 10 minutes (Cloud Functions) — cannot run long batch jobs.
- Debugging and local development are harder — simulating the cloud runtime locally is imperfect.
- High-traffic workloads can become expensive — per-invocation billing exceeds reserved container costs at sufficient scale.
Implementation notes
Minimize cold starts by keeping functions lean and dependencies small — use Lambda SnapStart (JVM) or keep runtimes in Python/Node where cold starts are under 100ms. Use provisioned concurrency for latency-sensitive functions that must be pre-warmed. Design functions to be idempotent — SQS and event sources guarantee at-least-once delivery, so duplicate invocations must be safe. Use Step Functions (AWS) or Durable Functions (Azure) for multi-step workflows rather than chaining functions directly — direct chaining produces invisible failure modes when intermediate functions fail. Externalize all state to managed services (DynamoDB, S3, ElastiCache) — assume no local file system or in-memory state persists between invocations. Monitor cold start rates, error rates, and p99 duration per function — not aggregate metrics.
Common failure modes
- Thundering cold start herd: Deployment triggers thousands of simultaneous invocations to a new function version, all cold starting at once — use traffic shifting (canary deployments) to warm up gradually.
- Silent failures in async invocations: An SQS-triggered function throws an uncaught exception — messages go to DLQ silently and nobody notices; DLQ alerting and monitoring are mandatory.
- Lambda function chains replacing orchestration: Function A triggers Function B which triggers C — one failed step leaves the workflow in an unknown state with no visibility. Use Step Functions.
- Cost overrun from runaway invocations: A misconfigured event source mapping processes an infinite loop of messages, billing thousands of dollars overnight — set maximum concurrency limits.
- VPC cold start penalties: Functions inside a VPC for RDS access previously had 10–30s cold starts (now improved with hyperplane ENI reuse) — understand your cloud provider's current VPC cold start behavior.
Decision checklist
- Is the workload event-driven and intermittent, or continuously loaded? (Serverless excels for the former.)
- Are cold start latencies acceptable for the use case, or is pre-warming/provisioned concurrency needed?
- Are all functions designed to be stateless and idempotent?
- Are DLQs and alerting configured for async function invocations?
- Are multi-step workflows using an orchestrator (Step Functions) rather than function chaining?
- Has vendor lock-in been evaluated — are migration costs acceptable, or is abstraction (SAM, Serverless Framework, CloudEvents) required?
Example use cases
- Image resizing on upload: S3 upload triggers a Lambda function that generates multiple thumbnail sizes and stores them back to S3 — scales from 1 to 100,000 uploads without configuration changes.
- Nightly reporting job: EventBridge Scheduler triggers a Lambda each night to run a database query and email a report — zero cost during the day.
- API backend for a low-traffic product: API Gateway + Lambda powers a REST API with no idle costs and no servers to manage — ideal for MVPs and early-stage products.
Related patterns
- Event-Driven Architecture — Serverless functions are naturally event-triggered consumers in an EDA topology.
- Microservices — Serverless is one deployment model for individual microservices, trading control for operational simplicity.
Further reading
- Serverless Architectures — Mike Roberts on Serverless at martinfowler.com.
- AWS Serverless Architecture Patterns — AWS documentation on serverless application patterns.
- Azure Serverless Overview — Microsoft Azure Architecture documentation.