In AWS Lambda, what is the difference between invoking a function with InvocationType RequestResponse and InvocationType Event, and who is responsible for retrying a failure in each case?
answer
- the caller's wait changes everything
- one hands back a payload, one a receipt
- InvocationType RequestResponse versus Event
- 202 Accepted means queued, not done
- whoever holds the error does the retrying
basics
~20 sRequestResponse is synchronous: the caller waits, receives the function's result or error, and must retry itself. Event is asynchronous: Lambda returns 202 immediately, queues the event internally, and retries a failed invocation on your behalf.
solid answer
~50 sThe `InvocationType` parameter on the Lambda `Invoke` API decides the whole shape of the interaction. With `RequestResponse` — the default — the caller's connection stays open for the duration of the execution, and the function's return value or error payload comes back in the response. Nothing in AWS retries an application error here; the caller owns that decision, and callers like API Gateway simply surface the failure. With `Event`, Lambda writes the event into an internal, AWS-managed queue and returns HTTP 202 with an empty body before the function has run. The caller never sees the result, success or failure. Lambda then invokes the function from that queue and, if the handler errors, retries it a couple of times before giving up. So the practical question is not "is it faster?" but "who is holding the error when it happens" — the caller, or AWS.
code
bash · 4 linesaws lambda invoke --function-name my-function \
--invocation-type Event \
--payload '{"orderId":"123"}' \
--cli-binary-format raw-in-base64-out /dev/nullgo deeper
Know the two InvocationType values by name and say plainly what comes back from each: a payload from RequestResponse, an empty 202 from Event. Add that Lambda retries only the asynchronous path.
Be ready to explain the mechanics behind the split — the AWS-managed queue behind Event, the FunctionError field on a 200 response, and why a synchronous caller sees latency the asynchronous one never does.
Show the operational consequence: with Event you have no response channel, so failure visibility has to be engineered with destinations and metrics. Say how you would detect a function silently failing on the asynchronous path.
Own the choice as an architectural one. Argue when a user-facing request should degrade into queued work, what that does to the consistency the client can rely on, and how the invocation model shapes the blast radius of a downstream outage.
## One parameter, two completely different contracts Every direct call into Lambda goes through the `Invoke` API action, and that action takes an `InvocationType` parameter with three legal values: `RequestResponse` (the default), `Event`, and `DryRun`. Everything else in this area — timeouts, error handling, retries, where a failed payload ends up — follows from which of those you chose. ## RequestResponse: the caller waits and owns the error With `RequestResponse`, the API call blocks while the function runs. When the handler returns, its serialized return value comes back as the response payload. The caller sees the latency of a cold start, of the handler body, and of every downstream call the handler makes. The trap here is that a *function* error is not a *request* error. If the handler throws, the `Invoke` call still returns HTTP 200. What tells you something went wrong is the `FunctionError` field in the response (set to `Handled` or `Unhandled`) and the `X-Amz-Function-Error` header; the payload then contains the serialized error rather than your result. Code that checks only the HTTP status will treat every crash as a success. ```bash aws lambda invoke --function-name my-function \ --invocation-type RequestResponse \ --payload '{"orderId":"123"}' \ --cli-binary-format raw-in-base64-out out.json ``` Nothing on the AWS side retries an application error on this path. AWS SDKs do retry — but only for the errors their retry policy covers, such as throttling and service-side 5xx responses, not for your handler blowing up. Services that invoke synchronously (API Gateway, an Application Load Balancer target, a function URL) pass the failure straight back to whoever called them. ## Event: Lambda takes custody of the event With `Event`, Lambda validates the request, writes the payload into an internal queue that AWS manages for you, and returns HTTP 202 Accepted with an empty body — typically in a few milliseconds, long before the function has started. There is no channel back to the caller: the return value is discarded, and so is the error. In exchange, Lambda owns delivery. It pulls from that queue, invokes the function, and if the invocation fails it retries. It also keeps retrying when the invocation is *throttled* rather than broken, which is what makes asynchronous invocation a natural shock absorber for bursty producers. Because the result is invisible to the caller, an asynchronously invoked function that matters must have somewhere for failures to land — a destination or dead-letter target — or the event simply disappears. ```bash aws lambda invoke --function-name my-function \ --invocation-type Event \ --payload '{"orderId":"123"}' \ --cli-binary-format raw-in-base64-out /dev/null ``` ## DryRun: the third value people forget `DryRun` validates the request — parameters and the caller's permission to invoke — without running the function, and returns HTTP 204 No Content. It is a permissions smoke test, not a way to "test" your handler. ## Which callers use which You rarely choose the invocation type by hand for event-driven functions; the calling service chose it for you. Front-door, request-shaped integrations invoke synchronously because someone is waiting for a response: API Gateway, an ALB, a function URL. Fire-and-forget event producers such as SNS and EventBridge invoke asynchronously. Poller-based sources are a third mechanism entirely, with their own batching and failure semantics. When *you* are writing the caller, pick on the question of who should be holding the error. If the client needs the answer to proceed, invoke synchronously and design the caller's retry and timeout behaviour deliberately. If the client only needs the work to eventually happen, invoke asynchronously so a brief downstream outage becomes a retry rather than a user-visible 500 — and accept that you must observe failures through metrics and a failure destination instead of a response body. ## Consequences people miss Asynchronous invocation is not faster; it just moves the wait. It is *at least once*, so handlers must tolerate seeing the same event twice. And a synchronous caller that retries on timeout may be retrying work that actually succeeded, because a timed-out response says nothing about whether the function finished.
- What does InvocationType DryRun actually do?It validates the request without executing the function: Lambda checks the parameters and whether the caller is permitted to invoke, then returns HTTP 204 No Content. It is a way to verify permissions and wiring in a deployment check, not a way to test handler logic — the handler never runs and no execution is billed.
- A synchronous Invoke returns HTTP 200. What must the caller still check before treating it as success?The `FunctionError` field on the response, or the `X-Amz-Function-Error` header. Lambda returns 200 as long as it managed to run the function at all; a handler that threw produces a 200 whose payload is the serialized error, with `FunctionError` set to `Handled` or `Unhandled`. Status-code-only error handling silently swallows every crash.
- Does asynchronous invocation make the overall work finish sooner?No — it only shortens the caller's wait. The function still takes the same time to run, and the event may sit briefly in Lambda's internal queue first, so end-to-end latency is usually slightly worse. What you gain is decoupling: the caller is not held hostage by the handler's duration or by a transient downstream failure.
saying these in an interview costs you the question
- Thinks an Event invocation returns the function's return value
- Assumes HTTP 200 from Invoke means the handler succeeded
- Believes AWS retries every failed invocation regardless of type
- Says asynchronous invocation makes the function itself run faster
- Claims the AWS SDK retries application errors on synchronous invokes