Serverless and FaaS: Event-Driven Compute Without Managing Servers
Learn serverless architecture and Function-as-a-Service, including cold starts, stateless execution, event-driven workflows, operational limits, and when serverless is the right choice.
Why Serverless?
Serverless is an execution model where the cloud provider manages the servers, runtime scaling, patching, capacity planning, and much of the operational plumbing. You still write code and own the architecture, but you do not provision long-running application servers for every workload.
Function-as-a-Service (FaaS) is the most common serverless compute model. You deploy small functions, and the platform runs them in response to events.
Key idea: Serverless does not mean "no servers." It means the server lifecycle is hidden behind a managed execution platform.
Traditional Compute vs Serverless
| Concern | Traditional Service | Serverless Function |
|---|---|---|
| Scaling | Configure instances or autoscaling | Platform scales per event |
| Billing | Pay for provisioned capacity | Pay per request and duration |
| Runtime | Long-running process | Short-lived invocation |
| State | Can keep local memory state | Must be stateless |
| Operations | Patch, deploy, size, monitor hosts | Monitor functions and managed services |
Function-as-a-Service
In FaaS, each function has a trigger, handler, runtime, configuration, and permissions.
Common Triggers
| Trigger | Example Use Case |
|---|---|
| HTTP request | API endpoint, webhook receiver |
| Queue message | Background job processor |
| Object storage event | Image resize after upload |
| Database stream | Build search index, sync analytics |
| Schedule | Nightly cleanup, report generation |
| Event bus | React to business events |
Handler Shape
type OrderPlacedEvent = {
orderId: string;
customerId: string;
totalAmount: number;
};
export async function handleOrderPlaced(event: OrderPlacedEvent) {
await reserveInventory(event.orderId);
await sendConfirmationEmail(event.customerId);
return { status: "accepted" };
}
The handler should be small, idempotent, and explicit about dependencies. Heavy orchestration, long waits, and hidden shared state make functions difficult to reason about.
Statelessness
Serverless functions can be reused between invocations, but you must not depend on local process memory for correctness. The platform may start a new execution environment at any time.
What Can Live Inside the Function?
| Data | Safe? | Notes |
|---|---|---|
| Database connection pool | Usually | Reuse for performance, but reconnect on failure |
| In-memory cache | Sometimes | Optimization only, never source of truth |
| User session | No | Store in Redis, database, or signed tokens |
| Idempotency key | No | Store externally with a uniqueness constraint |
| Config values | Yes | Load from environment or config service |
Do not rely on warm containers: A warm function can make repeated calls faster, but it is not a durability or coordination mechanism.
Cold Starts
A cold start happens when the platform must create a new execution environment before running your handler. The delay includes container setup, runtime startup, dependency loading, and initialization code.
Reducing Cold Start Impact
| Technique | Helps With | Trade-off |
|---|---|---|
| Keep dependencies small | Runtime initialization | Less framework convenience |
| Initialize lazily | First request path | More code discipline |
| Use provisioned concurrency | Latency-sensitive APIs | Higher fixed cost |
| Choose lighter runtimes | Startup time | Runtime ecosystem limits |
| Move work async | User-facing latency | Eventual consistency |
Cold starts matter most on synchronous user-facing paths. They matter less for background processing, scheduled jobs, and event consumers where a few hundred milliseconds do not affect user experience.
Event-Driven Serverless Workflows
Serverless works best when the system is naturally event-driven. A function receives an event, performs one bounded action, emits another event, and exits.
Orchestration vs Choreography
| Style | How It Works | Best For |
|---|---|---|
| Orchestration | A workflow engine coordinates each step | Business process with clear state machine |
| Choreography | Services react to events independently | Loosely coupled domain reactions |
Use orchestration when the process needs explicit retries, compensation, human-visible status, or strict ordering. Use choreography when downstream reactions can evolve independently.
Limits and Constraints
Serverless platforms intentionally limit execution. Those limits are part of the architecture.
| Constraint | Design Implication |
|---|---|
| Max execution duration | Break long jobs into steps |
| Memory and CPU coupling | Tune memory to get enough CPU |
| Payload size limits | Store large payloads externally |
| Concurrency limits | Protect databases and downstream services |
| Temporary disk only | Use object storage for durable files |
| Regional execution | Plan latency and data residency |
Concurrency is a backpressure tool: Unlimited function scaling can overload a database. Set concurrency limits, use queues, and size connection pools deliberately.
Data Access Patterns
Direct Function to Database
Simple, but high concurrency can create too many database connections.
Queue Buffered Writes
Better for smoothing spikes and protecting downstream systems.
Managed Service First
Good for file processing, analytics pipelines, and asynchronous workflows.
Observability
Serverless systems are distributed systems. You need correlation IDs, structured logs, metrics, and traces from the start.
| Signal | What to Track |
|---|---|
| Logs | Function input metadata, decision points, error context |
| Metrics | Invocations, errors, duration, throttles, concurrency |
| Traces | Cross-function and downstream service latency |
| Dead-letter queues | Failed events that need replay or manual inspection |
| Cost | Requests, duration, memory, provisioned concurrency |
When to Use Serverless
| Workload | Recommendation |
|---|---|
| Spiky traffic | Strong fit |
| Scheduled jobs | Strong fit |
| Event processing | Strong fit |
| Webhooks | Strong fit |
| Long-running compute | Usually avoid |
| Predictable high-throughput service | Compare cost carefully |
| Low-latency trading or gaming path | Usually avoid |
| Heavy stateful protocol | Avoid |
Common Anti-Patterns
| Anti-Pattern | Problem | Better Approach |
|---|---|---|
| One giant function | Hard to test, deploy, and reason about | Split by business action |
| Function chains everywhere | Debugging becomes painful | Use workflow engine or event bus |
| Direct database storm | Too many connections during spikes | Queue, pooler, or concurrency limits |
| Hidden local state | Breaks on cold start or reschedule | External durable state |
| No idempotency | Retries create duplicates | Store idempotency keys |
| Serverless for everything | Cost and limits surprise you | Match compute model to workload |
What to Remember for Interviews
- Serverless shifts operations: You manage architecture and code; the provider manages runtime capacity.
- Functions are stateless: Store durable state externally.
- Cold starts are workload-dependent: Critical for synchronous APIs, less critical for async jobs.
- Design for retries: At-least-once delivery means idempotency is mandatory.
- Protect downstream systems: Function scaling can overwhelm databases and third-party APIs.
Practice: Design a serverless image upload pipeline. Include upload, validation, thumbnail generation, virus scanning, metadata extraction, retries, and failure handling.