16 — Lambda and the Serverless Family: Code That Runs Without a Server in Sight
"Functions in the cloud" described Lambda but not the ecosystem around it, and the ecosystem is where the architecture actually lives. The settlement that landed: Lambda is event-driven code I never provision a server for, and around it sits a family of services that supply the triggers (EventBridge, S3, API Gateway), the edge variant (Lambda@Edge), and the container alternative (Fargate) — and the operational reality of all of it is layers, runtimes, versioning, and the cold start [1]. The function itself is small; the family is what makes it an architecture.
Lambda: code triggered by events
AWS Lambda runs my code in response to events and manages the compute underneath automatically [1]. I upload a function, wire it to a trigger, and AWS handles provisioning, scaling, and teardown. I pay per request and per millisecond of execution — nothing when the function isn't running. The supported runtimes include Node.js, Python, Java, Go, Ruby, and C#, and a Runtime API lets me bring others [3][4].
The mental shift from EC2 or ECS: I no longer think about instances, clusters, or capacity. I think about a function, its trigger, and its execution role. That's the whole unit. The trade-off for that simplicity is a set of constraints — execution time limits, the cold start, a stateless execution environment — which dictate where Lambda is the right tool and where it isn't.
Creating and invoking functions
A function has a name, a runtime, an execution role (an IAM role that grants the function's permissions — read this bucket, write to that table), and the code itself [2]. Once created, it's invoked in one of three ways:
- Synchronous (push) — a caller (the CLI, an API Gateway request, another service) invokes it and waits for the response.
- Asynchronous (event) — a service emits an event ("S3 object created") and Lambda runs the function; the emitter doesn't wait.
- Polling (stream-based) — Lambda itself polls a source (a DynamoDB stream, an SQS queue, Kinesis) and runs the function for each batch.
The first Lambda function I wrote was a few lines of Node.js that read an event and logged it — which is the right starting point. Everything else (IAM, layers, versioning) layers on top of that same shape.
Layers: sharing dependencies without bloating the package
A Lambda layer is a ZIP archive of libraries, custom runtimes, or other dependencies that a function can reference [5]. The layer is extracted to /opt in the execution environment at runtime. The value:
- Shared code across functions — a common logging utility, a company SDK, a heavy dependency, all maintained in one layer and attached to many functions.
- Smaller deployment packages — the function ZIP holds only the function's own code; the heavy stuff lives in a layer.
- Versioned and immutable — each layer version is a distinct artifact, so updating a layer never silently breaks functions pinned to the old one.
The discipline: anything shared across three or more functions, or anything large that changes rarely (a heavy ML inference library), belongs in a layer rather than being vendored into every function package.
Custom runtimes: any language, via the Runtime API
If my preferred language or version isn't in the managed runtimes, a custom runtime fills the gap [6]. It's a Linux executable that handles the conversation with the Lambda service via the Runtime API — receiving events, returning responses. Bring Rust, a specific Node version, an obscure interpreter — the Runtime API is the contract that makes any of them work. Most teams never need this; the supported runtimes cover the vast majority of cases. It exists for the long tail.
Versioning and aliases: safe deployment
Versioning creates immutable, numbered snapshots of a function's code plus configuration [7]. $LATEST is the working copy; publishing creates 1, 2, 3 — each a fixed artifact that never changes. An alias is a mutable pointer to a specific version (prod → 3, staging → 4).
The payoff: triggers and downstream services point at the alias, not the version. To deploy, I publish a new version, point prod at it (optionally with weighted traffic shifting for canaries), and roll back by repointing the alias. No trigger reconfiguration needed. This is the Lambda analog of immutable infrastructure — the function's identity stays stable while the code behind it changes.
EventBridge: the serverless event bus
EventBridge is the serverless event bus that connects applications using events from my own apps, SaaS services, and other AWS services [8]. It subsumes CloudWatch Events and adds richer routing, schema registries, and cross-account/cross-region delivery. The shape:
- Events are ingested onto a bus.
- Rules match events by pattern (or on a schedule — cron).
- Matched events are routed to targets — a Lambda function, a Step Function, an SQS queue, an API destination.
EventBridge is the backbone of event-driven architectures on AWS. "When an order is placed, emit an event; the inventory service, the notification service, and the analytics service each consume it independently" — that decoupling is EventBridge's job.
API Gateway: the HTTP front door
For HTTP-triggered Lambda, API Gateway is the front door [10]. It accepts HTTP requests, maps them to Lambda invocations, and returns the response — handling throttling, authorization, request/response transformation, and version management along the way. The combo (API Gateway + Lambda) is the canonical serverless web API: no servers to provision, scales to zero when idle, and bills per request.
Lambda@Edge and Fargate: the variants
Two more family members round out the serverless story:
- Lambda@Edge runs Lambda functions at CloudFront edge locations, so the code executes close to the user [11]. Use cases: rewriting URLs, customizing responses, A/B testing at the edge. The latency win comes from geography — the function runs where the user is, not where my region is.
- Fargate is the serverless container runtime [9]. It's not Lambda — it runs containers, not functions, and they stay up rather than scaling to zero. But it shares the serverless spirit: I specify CPU/memory per task and AWS runs it on capacity I never manage. When a workload is too long-running, stateful, or complex for Lambda's model but I still don't want to manage EC2, Fargate is the middle ground. (The notes on the ECS/EKS stack cover the full picture.)
The cold start: the honest constraint
The cold start is the latency hit Lambda pays on a function's first invocation after being idle, or after a code or dependency update [12]. AWS has to provision an execution environment, initialize the runtime, and load the code before the handler runs — work that's already done on a warm invocation. Cold starts are most noticeable on larger functions, on less-common runtimes (Java is famously slow to start), and on low-traffic functions that go idle between invocations.
The mitigations I reach for:
- Right-size the function — only load what the handler actually needs, lazily initializing heavy clients inside the handler rather than at module top.
- Provisioned concurrency — keep a pool of warm environments ready, eliminating cold starts for latency-critical paths (at extra cost).
- SnapStart (for Java) — restore from a pre-initialized snapshot instead of initializing from scratch.
The honest framing: most workloads tolerate the occasional cold start fine. It matters for synchronous, latency-critical paths (a user-facing API), and is largely invisible for asynchronous event processing.
How I use this
Lambda and its family are my default for event-driven, short-running, stateless work — the glue of an AWS architecture. The decision tree I run: if the work is triggered by an event (an upload, a webhook, a schedule) and finishes in seconds, Lambda is usually right; if the work is long-lived, stateful, or always-on, a container on Fargate or ECS is the better shape, because Lambda's billing and cold start work against always-on loads. When I do use Lambda, I keep functions small and single-purpose, share heavy or common code through layers, deploy through aliases with traffic shifting, and put provisioned concurrency only on the genuinely latency-critical synchronous paths. API Gateway fronts any HTTP-triggered functions; EventBridge carries the internal event flows. The way of thinking I keep is the family, not the function: Lambda is one shape of "no servers," Fargate is another, and picking between them is a question of state, runtime, and traffic pattern — not of which is "more serverless."
References
[1] Amazon Web Services, "What is AWS Lambda?," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/welcome.html
[2] Amazon Web Services, "Getting started with Lambda," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html
[3] Amazon Web Services, "Lambda runtimes," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
[4] Amazon Web Services, "Building Lambda functions with custom runtimes," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html
[5] Amazon Web Services, "AWS Lambda layers," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html
[6] Amazon Web Services, "Lambda custom runtimes," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
[7] Amazon Web Services, "Lambda function versioning and aliases," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html
[8] Amazon Web Services, "What is Amazon EventBridge?," EventBridge User Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html
[9] Amazon Web Services, "AWS Fargate," 2024. [Online]. Available: https://aws.amazon.com/fargate/
[10] Amazon Web Services, "What is Amazon API Gateway?," 2024. [Online]. Available: https://aws.amazon.com/api-gateway/
[11] Amazon Web Services, "Lambda@Edge with CloudFront," CloudFront Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html
[12] Amazon Web Services, "Reducing Lambda cold start times with SnapStart," Lambda Developer Guide, 2024. [Online]. Available: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html
Knowledge check · Question 1 of 5
A Lambda function's execution role controls…
Comments
Leave a Comment
You must be signed in to comment
0 Comments
No comments yet. Be the first to comment!