What is an AWS Lambda extension, how does it get into a function and run relative to your handler, and what are extensions typically used for?
answer
- companion code, not handler code
- separate process in the same environment
- layer contents under /opt/extensions
- started before the runtime, signalled at shutdown
- shares your memory, CPU and billed duration
basics
~20 sA Lambda extension is companion code that runs inside the same execution environment as your handler, registered through the Lambda Extensions API. External extensions run as separate processes started before the runtime; they ship as a layer with executables under /opt/extensions, or baked into a container image.
solid answer
~60 sAn extension is code that runs *alongside* your function rather than inside it, using the **Lambda Extensions API** to register for invocation and shutdown events. There are two flavours: an **external** extension is a separate process in the same execution environment, started before the runtime initialises and able to keep working briefly after the handler returns; an **internal** extension runs inside the runtime process itself, typically injected through a wrapper script or runtime-specific options. Packaging is the interesting part — an external extension is delivered as a layer whose executables sit in `/opt/extensions`, which is why extensions count against the five-layer cap, or baked into the image at the same path for image-packaged functions. Typical uses are observability and APM agents that forward telemetry through the Telemetry API, log shippers, and AWS's own parameter and secret caching extension. The cost is real: an extension shares the function's memory and CPU allocation, lengthens initialization, and the invocation is not complete — or billed-complete — until every extension has finished its post-invoke work.
code
bash · 10 lines# An external extension is just an executable in extensions/ inside a layer archive
mkdir -p extensions
cp ./build/telemetry-agent extensions/
chmod +x extensions/telemetry-agent
zip -r extension-layer.zip extensions/
aws lambda publish-layer-version \
--layer-name telemetry-agent \
--zip-file fileb://extension-layer.zip
# Extracted to /opt/extensions; Lambda starts every executable it finds therego deeper
Know that an extension is companion code that runs beside your handler in the same environment, usually added as a layer, and that observability agents are the common example.
Explain the packaging path — executables under /opt/extensions from a layer, or the same path in an image — and the three lifecycle events an extension registers for, including the shutdown flush.
Weigh the cost before adopting one: shared memory and CPU, longer initialization, post-invoke time that is billed and blocks the next request, plus the fleet-wide redeploy that a pinned layer version implies.
Decide whether the organisation standardises on an extension for telemetry at all, who owns and patches that layer, how its overhead is measured across the function fleet, and what the fallback is when a vendor agent regresses latency.
## The problem extensions solve Before extensions, anything a function needed alongside its business logic — pushing metrics to a vendor, fetching and caching a secret, shipping logs somewhere other than CloudWatch — had to live inside the handler. That coupled every function to the agent's lifecycle and made "add observability to all our functions" a code change in each one. Extensions decouple the two. They let companion code live in the same execution environment as the function, with its own lifecycle hooks, without the handler knowing it exists. ## Two kinds **External extensions** run as their own process in the execution environment. Lambda starts them *before* the runtime is initialised, they register with the Extensions API, and they then long-poll for events. Because they are separate processes, they can be written in any language regardless of the function's runtime — a Go binary alongside a Python function is normal. **Internal extensions** run inside the runtime process. There is no separate process; the runtime is started with modifications, commonly via a wrapper script that Lambda executes in place of the standard bootstrap, or through language-level options such as agent injection on the JVM. They suit anything that must be in-process, such as bytecode instrumentation. ## How they are packaged This is where extensions meet the packaging story. An external extension is an executable placed under `extensions/` in a layer archive, which Lambda extracts to **`/opt/extensions`** — Lambda starts every executable found in that directory. Consequences worth stating in an interview: - Extensions consume slots from the **five-layer-per-function cap**, and their bytes count against the same **250 MB unzipped** budget as everything else. - For a container-image function, where layers do not exist, you copy the extension into the image at `/opt/extensions` instead. - Because layer versions are immutable and pinned by ARN, updating a vendor's extension across a fleet is a per-function redeploy, exactly like any other layer. ```dockerfile # Image-packaged function: the extension goes to the same path a layer would use COPY --from=vendor/extension:latest /opt/extensions/ /opt/extensions/ ``` ## The lifecycle An extension registers with the Extensions API and declares which events it wants, then repeatedly calls the API's "next" endpoint, which blocks until something happens: 1. **Init** — extensions are started and register before the runtime initialises. Their startup time is part of the environment's initialization. 2. **Invoke** — each invocation is announced to registered extensions. The extension can do work concurrently with the handler. 3. **Shutdown** — when Lambda is about to destroy the environment it signals extensions, giving them a bounded window to flush buffered data. This is what makes an extension a *reliable* place to batch telemetry; buffered data in the handler would simply be lost when the environment goes away. Between invocations the environment is frozen, so an extension cannot do background work "while idle" — it resumes only when the next event arrives. That is a common misconception worth correcting: extensions do not give you a background daemon. ## What they cost Extensions are not free, and a senior answer names the price: - They share the function's **memory allocation** — an agent using 100 MB is 100 MB your handler does not have, at the memory size you are already paying for. - They share the **CPU** that the memory setting bought. - They lengthen **initialization**, because they start before the runtime does. - After the handler returns, the caller gets its response, but the environment cannot accept the next request until every extension has finished its post-invoke work — and that time counts toward billed duration. A chatty extension that makes a synchronous network call per invocation is a latency and cost regression across every function it is attached to. ## Typical uses - **Observability and APM.** Vendor agents that collect traces and metrics, buffer them, and flush on shutdown. The **Telemetry API** lets an extension subscribe to the platform's own logs, metrics and trace events and forward them elsewhere — the supported route for getting Lambda telemetry into a non-AWS backend. - **Log routing** to a destination other than CloudWatch Logs, without the function writing to it directly. - **Configuration and secret caching.** AWS publishes an extension that caches parameter and secret lookups in the execution environment behind a local HTTP endpoint, so warm invocations avoid a network call. - **Security and policy agents** that watch the environment. ## When not to use one If a single function needs one small thing, a library call in the handler is simpler and cheaper than an extra process. Extensions earn their keep when the same concern applies across many functions and must be decoupled from application code — and even then, measure the added init time and per-invocation overhead before rolling one out fleet-wide.
- Why is an extension a better place to buffer telemetry than the handler itself?Because extensions receive a shutdown event before the execution environment is destroyed, giving them a bounded window to flush what they buffered. Data buffered inside the handler has no such hook — when the environment goes away, anything not yet sent is lost. That shutdown signal is the main reason vendor agents are packaged as extensions at all.
- Can an extension do background work between invocations?No. The execution environment is frozen between invocations, so an extension's process makes no progress until the next event wakes it. Extensions are event-driven participants in the invocation lifecycle, not daemons. Anything that must run on a schedule independent of traffic belongs outside the function.
- What does adding a vendor extension cost you operationally?It consumes one of the five layer slots and part of the 250 MB unzipped budget, shares the function's memory and CPU, adds to initialization time, and holds the environment after the handler returns until it finishes its post-invoke work — which is billed. Rolling out an update means redeploying every consuming function, because layer version ARNs are pinned.
- How does an internal extension differ from an external one in practice?An internal extension runs inside the runtime process rather than as its own process, usually injected via a wrapper script that Lambda runs in place of the standard bootstrap, or by runtime-specific agent options. That gives it in-process access for instrumentation, at the cost of being tied to the function's language and of sharing the runtime's failure domain.
saying these in an interview costs you the question
- Thinks extensions run outside the function's memory allocation
- Believes an extension keeps working between invocations
- Says extensions are configured in code rather than packaged
- Assumes an extension must be written in the function's language
- Forgets extensions consume layer slots and the size budget