Serverless computing lets you run code without provisioning or managing servers. You write a function, deploy it, and the cloud provider handles everything else — scaling, patching, availability, and billing by the millisecond.
Despite the name, there are servers — you just never see them. The "serverless" refers to the developer experience: zero server management.
Serverless in 30 seconds
| Concept |
What it means |
| Serverless |
Run code without managing servers |
| FaaS |
Function as a Service — deploy individual functions |
| BaaS |
Backend as a Service — cloud-managed services (Auth, DB, Storage) |
| Trigger |
Event that invokes your function (HTTP, queue, schedule, etc.) |
| Cold start |
Delay when function starts for the first time |
| Warm start |
Fast execution when container is already running |
| Execution time |
Max runtime per invocation (e.g. 15 min for Lambda) |
| Pay-per-use |
Billed only for actual execution time, not idle time |
Traditional servers vs serverless
Before serverless, deploying an API meant:
- Provision a server — pick instance size, OS, runtime
- Install dependencies — Node.js, Python, packages
- Configure scaling — load balancer, auto-scaling groups
- Pay 24/7 — even when zero traffic hits your app
- Patch and update — OS patches, security updates
- Monitor the host — CPU, memory, disk alerts
With serverless:
- Write a function — just the business logic
- Deploy — one command
- It scales automatically — from 0 to millions of requests
- Pay per request — zero traffic = zero cost
- No patching — provider manages the runtime
How serverless actually works
User Request
│
▼
┌─────────────┐
│ API Gateway │ ← Receives HTTP request
└──────┬──────┘
│ Triggers
▼
┌─────────────┐
│ Function │ ← Your code runs here (Lambda, Cloud Function, etc.)
│ Container │
└──────┬──────┘
│ Reads/Writes
▼
┌─────────────────────────────────────────┐
│ Cloud Services: DB, Storage, Queue... │
└─────────────────────────────────────────┘
│
▼
Response to User
Lifecycle of a serverless invocation:
- Event triggers the function (HTTP request, S3 upload, SQS message…)
- Cloud provider allocates a container (or reuses a warm one)
- Your function code executes
- Function returns a response
- Container stays warm briefly, then is recycled
- You're billed only for execution duration + memory used
Types of serverless
| Type |
Description |
Examples |
| FaaS |
Individual functions triggered by events |
AWS Lambda, Azure Functions, Google Cloud Functions |
| BaaS |
Managed backend services |
Firebase, Supabase, Auth0, Stripe |
| Serverless containers |
Containers without server management |
Google Cloud Run, AWS Fargate, Azure Container Apps |
| Edge functions |
Functions at CDN edge nodes |
Cloudflare Workers, Vercel Edge Functions, Fastly Compute |
| Serverless databases |
Auto-scaling databases |
PlanetScale, Neon, DynamoDB on-demand, Aurora Serverless |
| Serverless queues |
Managed message queues |
SQS, Azure Service Bus, Cloud Pub/Sub |
FaaS vs BaaS
|
FaaS (Function as a Service) |
BaaS (Backend as a Service) |
| You write |
Business logic functions |
Minimal or no code |
| You manage |
Function code |
Nothing |
| Examples |
AWS Lambda, Cloud Functions |
Firebase Auth, Stripe, Auth0 |
| Flexibility |
High — any logic |
Low — fixed features |
| Cost model |
Per invocation + duration |
Per usage tier or transaction |
| Best for |
Custom backend logic |
Standard auth, payments, storage |
Major serverless platforms compared
| Platform |
Provider |
Languages |
Max Timeout |
Free Tier |
Cold Start |
| AWS Lambda |
Amazon |
Node, Python, Java, Go, Ruby, .NET, custom |
15 min |
1M req/mo |
100ms–1s |
| Azure Functions |
Microsoft |
C#, JS, Python, Java, PowerShell |
10 min (Consumption) |
1M req/mo |
300ms–2s |
| Google Cloud Functions |
Google |
Node, Python, Go, Java, Ruby, PHP |
60 min |
2M req/mo |
200ms–2s |
| Google Cloud Run |
Google |
Any (Docker container) |
60 min |
2M req/mo |
Fast |
| Cloudflare Workers |
Cloudflare |
JS, TS, Wasm |
30s CPU / 15min wall |
100k req/day |
~0ms (V8 isolates) |
| Vercel Functions |
Vercel |
Node, Python, Go, Ruby |
60s (Pro), 10s (Hobby) |
Included |
200ms–1s |
| Netlify Functions |
Netlify |
Node, Go |
10s (sync), 15min (background) |
125k req/mo |
200ms–1s |
| Deno Deploy |
Deno |
TypeScript/JavaScript |
50ms CPU |
100k req/day |
~0ms |
Your first serverless function
AWS Lambda (Node.js)
// handler.js
export const handler = async (event) => {
const name = event.queryStringParameters?.name ?? 'World';
return {
statusCode: 200,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: `Hello, ${name}!` }),
};
};
Deploy with Serverless Framework:
# serverless.yml
service: hello-api
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
functions:
hello:
handler: handler.handler
events:
- httpApi:
path: /hello
method: GET
npm install -g serverless
serverless deploy
# → Endpoint: GET - https://xyz.execute-api.us-east-1.amazonaws.com/hello
Google Cloud Functions (Python)
# main.py
import functions_framework
from flask import jsonify
@functions_framework.http
def hello(request):
name = request.args.get('name', 'World')
return jsonify(message=f'Hello, {name}!')
gcloud functions deploy hello \
--runtime python312 \
--trigger-http \
--allow-unauthenticated
Cloudflare Workers
// worker.js
export default {
async fetch(request) {
const url = new URL(request.url);
const name = url.searchParams.get('name') ?? 'World';
return new Response(JSON.stringify({ message: `Hello, ${name}!` }), {
headers: { 'Content-Type': 'application/json' },
});
},
};
npx wrangler deploy
Common serverless triggers
| Trigger |
Description |
Use case |
| HTTP / API Gateway |
REST or WebSocket endpoint |
APIs, webhooks |
| Schedule (Cron) |
Time-based invocation |
Reports, cleanup jobs |
| Object storage |
File upload event (S3, GCS) |
Image resizing, ETL |
| Queue |
SQS, RabbitMQ, Pub/Sub message |
Async processing |
| Database stream |
DynamoDB Streams, Firestore triggers |
Real-time sync |
| Email / SNS |
Notification event |
Email processing |
| Auth event |
User signup, login |
Post-registration logic |
| IoT |
Sensor data ingestion |
IoT pipelines |
| Stream |
Kinesis, Kafka, Event Hub |
Real-time analytics |
Cold starts explained
A cold start happens when there is no warm container ready for your function:
First request (cold start):
─────────────────────────────────────────────────
Init container │ Download code │ Execute
~200ms │ ~100ms │ ~50ms
─────────────────────────────────────────────────
Total: ~350ms+
Subsequent requests (warm start):
─────────────────
Execute
~50ms
─────────────────
Total: ~50ms
What causes cold starts?
| Factor |
Impact on cold start |
| Language runtime |
JVM (Java/Kotlin) = slowest; Node/Python = medium; Compiled (Go/Rust) = fastest |
| Package size |
More dependencies = longer init |
| Memory allocation |
More memory = faster CPU = faster init |
| VPC configuration |
Adding VPC adds 1–10s (AWS Lambda) |
| Inactivity |
No traffic for 5–15 min = container recycled |
| Concurrency |
Sudden spike = many cold starts simultaneously |
How to minimize cold starts
| Strategy |
Details |
| Provisioned concurrency |
Pre-warm N containers (costs money) |
| Keep-alive pings |
Schedule a request every 5 min |
| Smaller deployment packages |
Trim dependencies, use tree-shaking |
| Choose faster runtime |
Node.js/Python over Java for latency-sensitive code |
| Avoid VPC (if possible) |
VPC adds significant init time on Lambda |
| Use Cloudflare Workers |
V8 isolates start in <1ms (no cold start) |
| Lambda SnapStart |
AWS feature for Java — snapshot and restore |
Serverless pricing models
AWS Lambda pricing (2025)
| Dimension |
Price |
| Requests |
$0.20 per 1 million requests |
| Duration (x86) |
$0.0000166667 per GB-second |
| Duration (ARM/Graviton) |
$0.0000133334 per GB-second (20% cheaper) |
| Free tier |
1M requests/mo + 400,000 GB-seconds/mo |
Example cost calculation:
10 million requests/month
Average duration: 200ms per invocation
Memory: 256 MB
GB-seconds = 10,000,000 × 0.2s × 0.25GB = 500,000 GB-s
Cost = (10M - 1M free) × $0.20/M = $1.80
+ (500k - 400k free) × $0.0000166 = $1.67
Total = ~$3.47/month
Compare to: 1× t3.small EC2 instance = ~$15/month (always on)
Pricing comparison
| Provider |
Requests (free) |
Duration (free) |
Paid requests |
| AWS Lambda |
1M/mo |
400k GB-s/mo |
$0.20/M |
| Google Cloud Functions |
2M/mo |
400k GB-s/mo |
$0.40/M |
| Azure Functions |
1M/mo |
400k GB-s/mo |
$0.20/M |
| Cloudflare Workers |
100k/day |
10ms CPU-time/req |
$5/mo (10B req) |
| Vercel Functions |
Generous included |
Included in plan |
Paid plan |
Real-world use cases
| Use case |
How serverless helps |
| REST API backends |
No server management; scales to zero when unused |
| Image/video processing |
S3 upload triggers Lambda → resize, compress, transcode |
| Webhooks |
Stripe, GitHub, Twilio callbacks processed by a function |
| Scheduled jobs |
Cron-triggered functions for reports, cleanup, sync |
| Authentication |
Pre/post-authentication hooks in Auth0, Cognito |
| Real-time notifications |
Database trigger → push notification |
| ETL pipelines |
Queue message → transform → write to data warehouse |
| Chatbots |
Stateless request/response handler |
| IoT data ingestion |
High-concurrency sensor data processing |
| A/B testing / feature flags |
Edge function modifies response based on user |
| PDF/email generation |
On-demand document generation |
| GraphQL resolvers |
Each resolver as a function |
Serverless vs containers vs VMs
|
Virtual Machines |
Containers (Docker) |
Serverless |
| Management |
You manage OS, patches |
You manage container |
Provider manages everything |
| Startup time |
Minutes |
Seconds |
Milliseconds (warm) |
| Scaling |
Manual or scheduled |
Kubernetes (complex) |
Automatic, instant |
| Minimum cost |
Always-on VM |
Running pod |
Zero (pay per use) |
| State |
Stateful |
Stateful or stateless |
Stateless (ephemeral) |
| Execution limit |
Unlimited |
Unlimited |
Seconds to minutes |
| Vendor lock-in |
Low |
Low |
High |
| Debugging |
SSH into box |
Exec into container |
Logs + tracing only |
| Best for |
Legacy apps, DBs |
Microservices |
Event-driven workloads |
| Examples |
EC2, Azure VM |
ECS, GKE |
Lambda, Cloud Functions |
Serverless vs microservices
These are often confused. They solve different problems:
|
Microservices |
Serverless |
| What it is |
Architectural pattern |
Deployment/infrastructure model |
| Unit of deployment |
Service (often a container) |
Function |
| State |
Can be stateful |
Usually stateless |
| Communication |
HTTP, gRPC, queues |
Events, HTTP |
| Scaling |
Per service |
Per function (automatic) |
| Can combine? |
Yes — serverless microservices |
Yes — functions implement services |
You can have: serverless microservices (small functions per domain) or container-based microservices.
Serverless architecture patterns
1. Simple API
Client → API Gateway → Lambda function → Database
2. Async processing
Client → API → SQS Queue → Lambda worker → Database
→ Notify user
3. Event-driven pipeline
S3 upload → Lambda (resize) → S3 output
→ Lambda (extract metadata) → DynamoDB
→ Lambda (send notification) → SNS/SQS
4. Saga pattern (distributed transactions)
Lambda A → publishes event
→ Lambda B handles event
→ publishes event
→ Lambda C handles event
→ success or compensating transaction
5. Fan-out
SNS topic → Lambda A (send email)
→ Lambda B (update DB)
→ Lambda C (log analytics)
Serverless frameworks and tools
| Tool |
Purpose |
Language |
| Serverless Framework |
Deploy to any cloud with YAML config |
Any |
| AWS SAM |
AWS-native serverless deployment |
Any |
| AWS CDK |
Infrastructure as code for AWS |
TypeScript, Python, Java, Go |
| SST (Ion) |
Full-stack serverless on AWS |
TypeScript |
| Terraform |
IaC across all clouds |
HCL |
| Pulumi |
IaC with real programming languages |
TypeScript, Python, Go |
| Architect |
AWS-specific DX framework |
Node.js |
| Chalice |
Python serverless on AWS |
Python |
| Zappa |
Deploy Django/Flask to Lambda |
Python |
| Claudia.js |
Deploy Node.js to Lambda |
Node.js |
Serverless Framework example (full stack)
# serverless.yml
service: my-api
frameworkVersion: '3'
provider:
name: aws
runtime: nodejs20.x
region: eu-west-1
environment:
TABLE_NAME: !Ref UsersTable
functions:
getUser:
handler: src/users.get
events:
- httpApi:
path: /users/{id}
method: GET
createUser:
handler: src/users.create
events:
- httpApi:
path: /users
method: POST
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: users
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
Observability in serverless
Since you can't SSH into a server, observability is critical:
| Tool |
What it provides |
| AWS CloudWatch |
Logs, metrics, alarms, dashboards |
| AWS X-Ray |
Distributed tracing across services |
| Datadog |
Full-stack monitoring + APM |
| New Relic |
Performance monitoring + alerting |
| Lumigo |
Serverless-specific tracing and debugging |
| Epsagon |
Distributed tracing for serverless |
| Sentry |
Error tracking and performance |
| OpenTelemetry |
Open standard for traces, metrics, logs |
Key metrics to watch:
| Metric |
What it tells you |
| Invocation count |
Traffic volume |
| Error rate |
Function failures |
| Duration (p50/p95/p99) |
Latency distribution |
| Throttle count |
Concurrency limit hits |
| Cold start rate |
% of cold-started invocations |
| Concurrent executions |
Scaling in real time |
| Cost |
Per-function billing |
Limitations and trade-offs
| Limitation |
Details |
| Execution timeout |
Lambda: 15 min; Cloud Functions: 60 min — no long-running processes |
| Cold starts |
Extra latency on first request after idle period |
| Stateless |
No in-memory state between invocations; use external state store |
| Vendor lock-in |
AWS Lambda code often ties you to AWS services |
| Concurrency limits |
Default 1,000 concurrent Lambdas (can be raised) |
| Debugging difficulty |
No interactive debugger; reproduce locally with SAM/LocalStack |
| Payload size |
Lambda sync: 6MB request/response; async: 256KB |
| No WebSockets |
Native support limited; use API Gateway WebSocket API |
| Local development |
Needs LocalStack or emulators to simulate cloud |
| Not for CPU-heavy tasks |
Heavy ML inference, video encoding → use containers or VMs |
When to use serverless (and when not to)
Use serverless when:
| Scenario |
Why serverless fits |
| Unpredictable traffic |
Scales 0→1M without pre-provisioning |
| Infrequent jobs |
Pay-per-use beats always-on server |
| Event-driven workflows |
Triggers connect naturally to FaaS |
| Rapid prototyping |
No server setup, deploy in minutes |
| Microservices |
Each function is independently deployable |
| Variable workloads |
Burst traffic auto-scales |
| Small teams |
No ops overhead, focus on code |
Don't use serverless when:
| Scenario |
Better alternative |
| Long-running tasks (>15 min) |
Container, EC2, batch job |
| Latency-critical (p99 < 10ms) |
Containerized service with provisioned concurrency |
| High-traffic constant workloads |
Containers often cheaper at sustained high RPS |
| Stateful workloads |
Containerized service + database |
| Heavy CPU/GPU compute |
EC2 GPU instances, SageMaker |
| Legacy monolith migration |
Lift-and-shift to containers first |
| Complex debugging required |
Local debugger in container is easier |
Serverless security best practices
| Practice |
Why it matters |
| Least-privilege IAM roles |
Each function only gets permissions it needs |
| Secrets in Secrets Manager / Parameter Store |
Never hardcode API keys in code |
| Input validation |
Functions are public endpoints — validate everything |
| VPC for internal resources |
Restrict DB access to private subnet |
| Enable CloudTrail |
Audit all API calls |
| Dependency scanning |
Outdated packages are the #1 attack vector |
| Concurrency limits |
Set per-function limits to prevent DDoS cost spikes |
| WAF on API Gateway |
Block malicious traffic before it hits your function |
| Timeouts and retries |
Prevent runaway costs from infinite loops |
Serverless vs traditional: cost comparison
Scenario: API handling 10M requests/month, 200ms avg, 128MB memory
| Option |
Monthly cost |
Notes |
| AWS Lambda |
~$2–4 |
Scales to zero; free tier covers small apps |
| t3.micro EC2 (1 node) |
~$8 |
Running 24/7 whether traffic or not |
| t3.small EC2 (1 node) |
~$15 |
Handles more traffic |
| ECS Fargate (1 task) |
~$30 |
Container without server mgmt |
| EKS (Kubernetes) |
~$100+ |
Includes cluster overhead |
Tipping point: For sustained high traffic (millions of req/hour), containers become cheaper. For bursty or low traffic, serverless wins.
Serverless vs serverless containers
|
FaaS (Lambda) |
Serverless Containers (Cloud Run/Fargate) |
| Unit |
Function |
Container image |
| Code style |
Handler function |
Full web server |
| Startup |
Faster (smaller) |
Slower (full container) |
| Timeout |
15 min (Lambda) |
60 min (Cloud Run) |
| Vendor lock-in |
Higher |
Lower (Docker is portable) |
| Local testing |
Needs SAM/LocalStack |
docker run works locally |
| Long connections |
Limited |
Yes (HTTP streaming) |
| Best for |
Event handlers, small APIs |
Microservices, larger APIs |
Cloud Run example:
# Dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]
gcloud run deploy my-api \
--source . \
--region us-central1 \
--allow-unauthenticated
# Scales from 0 to N automatically
Serverless design principles
| Principle |
Details |
| Single responsibility |
Each function does one thing |
| Stateless |
Store state externally (DynamoDB, Redis, S3) |
| Idempotent |
Same input always produces same output (safe to retry) |
| Event-driven |
React to events rather than polling |
| Fail fast |
Validate input immediately; don't waste execution time |
| Minimize cold start |
Small packages, lazy loading, right memory |
| Observability first |
Structured logs + correlation IDs from day one |
| Secure by default |
Least privilege, validate all inputs |
Common mistakes
| Mistake |
Better approach |
| Monolith in a function |
Split large functions by responsibility |
| Storing state in function memory |
Use Redis, DynamoDB, or S3 |
| Ignoring cold starts |
Use provisioned concurrency or warm-up pings for latency-sensitive paths |
| Keeping DB connections open |
Use connection pooling (RDS Proxy) or serverless DBs |
| Not setting timeouts |
Always set function + downstream timeouts |
| Using VPC unnecessarily |
VPC adds cold start time; only use if needed |
| Overly large deployment packages |
Use Lambda layers, tree-shake dependencies |
| No dead-letter queue |
Failed async invocations are silently lost without DLQ |
Serverless vs related terms
| Term |
Relationship to serverless |
| Cloud computing |
Serverless is a subset of cloud computing |
| Microservices |
Architectural pattern; can be implemented as serverless |
| Containers |
Alternative deployment model; serverless containers bridge both |
| PaaS |
Higher abstraction than IaaS; serverless goes further |
| Edge computing |
Serverless at the network edge (Cloudflare Workers) |
| Event-driven architecture |
Serverless is a natural fit for EDA |
| DevOps |
Serverless reduces ops burden but needs DevOps practices |
| NoOps |
Aspirational state enabled by serverless + managed services |
FAQ
Q: Is serverless really serverless?
No — there are physical servers somewhere. "Serverless" means you don't manage any servers. The cloud provider owns, patches, and scales the infrastructure.
Q: Can I run a database serverless?
Yes. Options include: DynamoDB (on-demand mode), Aurora Serverless v2, PlanetScale, Neon (serverless Postgres), Turso (SQLite at the edge), and MongoDB Atlas Serverless.
Q: Is serverless cheaper than containers?
Depends on traffic. For low/bursty traffic: serverless wins (scales to zero). For sustained high RPS (e.g. 1000 req/sec 24/7): containers are often cheaper. Run the math for your specific workload.
Q: How do I test serverless functions locally?
- AWS Lambda: AWS SAM CLI (
sam local invoke), LocalStack
- Cloud Functions: Functions Framework (
functions-framework --target=hello)
- Cloudflare Workers: Wrangler (
wrangler dev)
- Any: Write pure functions with no cloud SDK dependencies, then test with unit tests
Q: What languages can I use for serverless?
AWS Lambda natively supports Node.js, Python, Java, Go, Ruby, .NET, and PowerShell. Via custom runtimes, you can use any language (Rust, PHP, Swift, etc.). Cloud Run/Fargate support any language that runs in Docker.
Q: Is serverless good for machine learning inference?
For lightweight models: yes. AWS Lambda supports up to 10GB memory and 10GB ephemeral storage — enough for small models. For heavy inference (large LLMs, GPUs), use SageMaker, GPU instances, or dedicated containers.