Functions and Event-Driven Processing
Adapted from: Brendan Burns, Designing Distributed Systems (O'Reilly), Chapter 9 — rewritten and condensed for teaching.
Earlier lessons assumed long-running servers always ready for traffic — right for heavy load, large in-memory state, or background work. Another class of apps only needs to exist briefly for a request or react to an event. Public clouds productized that style as function-as-a-service (FaaS); similar runtimes also sit on cluster orchestrators in private clouds. FaaS is often one piece of a larger design, not the whole system.
Serverless means you do not manage the servers. Event-driven FaaS means code runs in response to discrete events. They overlap but are not the same:
| Serverless | Event-driven | |
|---|---|---|
| Multitenant container platform (CaaS) | ✓ | not necessarily |
| Open-source FaaS on machines you own | not really | ✓ |
| Cloud Lambda / Cloud Functions style | often both | ✓ |
Pick event-driven, serverless, or both based on the problem — not the buzzword.
When FaaS Makes Sense
FaaS is a strong tool in a narrow context. Stretching it into every service produces brittle, hard-to-operate designs.
Benefits (mostly for developers)
- Short path from source → running code (little packaging ceremony).
- Automatic scale-out when traffic rises; failed instances restart elsewhere.
- Functions are stateless building blocks — systems tend to stay modular (network is the only integration path; state lives in storage services).
Challenges
Forced decoupling cuts both ways:
- Hard to see the whole service, how functions wire together, and why something failed.
- Easy to create accidental infinite call loops (
A → B → C → A) until timeouts burn money — each function is independent, so dependency graphs are not obvious in the code. - You need monitoring and alerting early; that ops cost offsets some of FaaS’s deploy simplicity.
When FaaS is a poor fit
| Need | Why FaaS struggles |
|---|---|
| Long background work (transcode, compress logs) | Time-bounded, event-triggered runs; scheduled pings help alarms, not generic batch jobs |
| Large data in memory (search indexes) | Cold start must load state while the user waits; if load stays high enough to keep functions warm, you may be overpaying vs a long-running service |
| Sustained high RPS | Pay-per-request grows ~linearly; VM/container pricing + reservations often wins once CPUs stay busy |
A common evolution: start on managed FaaS, later run open-source FaaS on Kubernetes (or move hot paths to long-running services) to keep the programming model while changing the cost model.
Check: when to use FaaS
FaaS fit
1 / 3Which statement best separates “serverless” from “event-driven FaaS”?
Pick an answer to see if you are right.
Pattern: Decorator (Request / Response Transformation)
FaaS shines at small, stateless transforms between a client and another service — validate, default fields, enrich headers — then forward. That is the decorator idea (similar to Python decorators): wrap an existing API without stuffing the logic into the core handler.
flowchart LR
CLIENT[Client]
DEC[Decorator function]
API[Core API service]
CLIENT --> DEC
DEC -->|transformed request| API
API --> DEC
DEC --> CLIENT
Why FaaS instead of an always-on adapter container?
- Defaulting/validation is often cheap — you may not want it scaled 1:1 with a heavy API.
- Easy to experiment with transforms, then pull winners into the main service later.
Hands On: Request defaulting
Implement a handler that fills missing name and color, then calls the real API.
On a Kubernetes cluster with Kubeless installed, the book’s flow looks like kubeless function deploy add-defaults --runtime python27 --handler defaults.handler --from-file defaults.py --trigger-http. The important design idea is the decorator, not the specific FaaS vendor.
Check: decorator pattern
Request decorator
1 / 1Why might you run JSON field defaulting as a FaaS decorator instead of inside the core API process?
Pick an answer to see if you are right.
Pattern: Handling Events
Requests usually sit in a longer session (pages, API conversations). Events are often one-shot and asynchronous: user signed up, file uploaded, machine rebooting. Variable rates and independence make events a natural FaaS workload — often beside a main app server.
Example: two-factor authentication. After password success, fire a webhook to a function that generates a code, registers it with the login service, and texts the user — so the login page is not blocked on SMS latency.
Hands On: Two-factor code registration
Implement the core logic (SMS library stubbed).
Check: events vs requests
Event handling
1 / 1Why is sending a 2FA text via an async FaaS often better UX than doing it inside the login request handler?
Pick an answer to see if you are right.
Pattern: Event-Based Pipelines
Some flows look like flowcharts: a directed graph of webhooks/functions, edges as HTTP (or other) calls, little shared memory beyond a context id in storage.
Vs microservices:
- Pipeline steps are event-triggered and often short-lived; microservices are usually long-running.
- Pipelines easily mix human steps (approve a ticket) with automation.
Example CI-ish flow: commit → build → on success open approval ticket → on close push to prod; on failure file a bug and stop.
Hands On: New user signup pipeline
Orchestrate required handlers (always) and optional handlers (only if a flag/key is present on the signup payload).
Factored this way, each step stays a few lines focused on one job; the pipeline (required vs optional webhook lists) is what you reason about at a high level.
Check: pipelines
Event pipelines
1 / 2What mainly distinguishes an event-based FaaS pipeline from a typical microservices architecture?
Pick an answer to see if you are right.
- FaaS / event-driven code runs for discrete events; serverless is about ops ownership — do not conflate them.
- Great for stateless transforms, async side effects, and pipelines of small handlers; weak for long jobs, huge warm state, and always-on heavy RPS without a pricing rethink.
- Decoupling improves modularity but demands observability (watch for cycles and silent failures).
- Decorator, event handler, and event pipeline are three practical ways to drop FaaS beside (not instead of) core services.
- Ideal designs often compose FaaS with long-running platforms (e.g. Kubernetes) as the system grows.
Further Reading
- Brendan Burns — Designing Distributed Systems (O'Reilly), Chapter 9 (Functions and Event-Driven Processing)
- Scatter/Gather — long-running parallel request trees (contrast with short-lived functions)
- Ownership Election — next: exclusive leaders, distributed locks, and leases
- Replicated Load-Balanced Services — the always-on tier FaaS often sits in front of or beside
- The Sidecar Pattern / Ambassadors — single-node adapters vs network-level FaaS decorators