Articles
AWS Lambda SQS Interview Questions: Partial Batch Failures, Retries, and Concurrency
Practice AWS Lambda SQS interview questions with partial batch JSON, FIFO retry traces, tested Python handlers, visibility timeouts, and concurrency scenarios.
AWS Lambda SQS interview questions become easier when you separate three decisions: which messages the handler reports as failed, when those messages can be received again, and how much concurrent work the system can safely admit. A correct JSON response solves only the first of those problems.
This guide uses current AWS documentation and an original, locally executed Python handler exercise. Official facts describe the managed service; local results describe the small test; editorial scenarios supply interview practice assumptions. These are not candidate-reported Amazon interview questions or predictions of a particular hiring process.
For this integration, be ready to trace one batch all the way from processing to acknowledgment.
Start with the event source mapping
Official behavior: Lambda polls SQS and invokes the function synchronously. Successfully processed batches are deleted; received messages remain temporarily hidden by the visibility timeout. An ordinary batch failure makes the batch eligible for another delivery after that timeout. Duplicate processing remains possible.
The word “synchronously” matters here. Do not import the retry count for Lambda's separate asynchronous invocation mechanism into an SQS answer. Identify the integration before naming its retry policy.
For an interview, draw four boxes: source queue, event source mapping, handler, and business destination. Then mark where the business write becomes durable and where the managed service learns the handler's outcome. A crash between those boundaries is a useful starting point for a follow-up question.
Our example assumes one batch containing messages A, B, and C. A and C are valid; processing B raises an exception. The identifiers are simplified stand-ins for the actual SQS messageId strings.
Predict the result before writing the handler
Official configuration: partial batch responses require ReportBatchItemFailures on the event source mapping and a response listing failed message IDs. A top-level exception still fails the whole batch. For FIFO, AWS recommends stopping after the first failure and reporting both failed and unprocessed records.
The following are original traces derived from those rules, assuming processing begins with A and the managed service receives the indicated outcome:
| Handler outcome | What the trace means |
|---|---|
| A succeeds; B raises out of the handler | The invocation fails. A's earlier success does not create a partial acknowledgment. |
| A and C succeed; B is caught and reported | With partial reporting enabled, B is the retry candidate from this response. |
| B is caught, but the handler returns an empty failure list | The handler has represented the batch as successful. Logging the error does not report it. |
| A succeeds; B fails; C is left unprocessed in a FIFO batch | The response must include B and C in this conservative stop-on-failure approach. |
These are retry sets, not promises that the very next invocation contains exactly those records. Queue delivery, other traffic, and duplicate delivery still affect what is observed later.
A good answer also distinguishes “failed” from “not attempted.” In the FIFO trace, C did not experience a processing exception. It still belongs in the response because the handler has not completed it.
Return the SQS message ID, not a business key
For the standard-queue trace, the response is:
{
"batchItemFailures": [
{"itemIdentifier": "B"}
]
}
Here B represents the failed record's messageId. It is not a receipt handle, order number, or custom correlation ID. Those other identifiers can be useful elsewhere, but they do not substitute for this response field.
Inspect the mapping configuration as well as the code. A code review that finds the right object shape but never checks FunctionResponseTypes has not verified the integration. Conversely, enabling the setting does not repair a handler that swallows failures and returns success.
Editorial review exercise: a teammate says, “I added an error log, so Lambda will retry B.” Ask them to show the returned object and whether the invocation throws. Logs are diagnostic evidence; the response and invocation status form the service contract.
If an unexpected error occurs after the loop while building the response, previously successful work can face another delivery. Design the business operation for that possibility rather than relying on the loop's happy-path bookkeeping.
Test standard and FIFO control flow locally
This original helper accepts a processing function so failures can be injected without AWS credentials. The fifo flag chooses a conservative policy: after one failure, leave every remaining record unprocessed and report it.
def handle(event, process, fifo=False):
failures = []
blocked = False
for record in event['Records']:
if blocked:
failures.append({'itemIdentifier': record['messageId']})
continue
try:
process(record)
except Exception:
failures.append({'itemIdentifier': record['messageId']})
blocked = fifo
return {'batchItemFailures': failures}
Observed locally: ten Python cases passed. Each queue policy was tested with no failures, failure at A, failure at B, failure at C, and failures assigned to A and C. The assertions checked attempted records, successful records, and the exact returned identifiers.
With B failing, standard mode attempted A, B, C and returned B. FIFO mode attempted only A and B, returning B and C. With A failing under FIFO, neither B nor C was attempted, and all three identifiers were returned.
This is a handler control-flow test. It does not execute AWS polling, visibility timing, queue deletion, throttling, or redrive. Those service behaviors are grounded in the linked documentation, not claimed as cloud-test observations.
The helper also omits production logging, deadline handling, and business idempotency. If you add parallel processing, revisit the ordering and completion assumptions before treating the sequential test as evidence for the new implementation.
Explain the FIFO trade-off without overclaiming
Our FIFO fixture treats the remaining batch conservatively. It does not attempt a more elaborate optimization across independent message groups. If the interviewer introduces multiple groups, first clarify which records share an ordering dependency and what the proposed batch processor guarantees.
For one order's sequence, imagine A creates the order, B reserves inventory, and C confirms fulfillment. Proceeding with C after B fails can violate the business sequence even if C's code returns successfully. The question is about valid state transitions, not simply whether exceptions can be caught.
Now change the scenario: B is malformed and will never succeed. Endless retry does not repair its payload. Explain who inspects the failed message, how corrected work enters the system, and how the business handles the missing transition. A recovery design needs an owner and a reconciliation rule.
Do not answer every FIFO follow-up with “increase concurrency.” A blocked dependency requires a correctness decision. More independent workers do not make fulfillment valid before inventory reservation.
Calculate a visibility budget from the actual settings
AWS guidance: the SQS configuration page recommends visibility timeout of at least six times the function timeout, adding the batching window when used. It separately requires function timeout not to exceed visibility timeout. Those are a recommendation and a validation constraint, respectively.
Original arithmetic exercise: the function timeout is 30 seconds and the standard queue's batching window is 5 seconds. The documented recommendation gives 6 × 30 + 5 = 185 seconds. A 40-second visibility timeout may satisfy the simpler comparison with 30, but it does not satisfy that recommendation.
Explain what you would measure next: complete-batch duration, downstream latency, and how processing time changes with batch size. A handler that processes records sequentially needs enough time for the batch, not just the typical duration of one record.
Suppose ten records each take roughly two seconds in a clean local scenario. Twenty seconds of processing leaves little room inside a 30-second function timeout for slow calls or retries. That arithmetic is an initial estimate, not a production latency guarantee.
A longer visibility timeout also changes how long failed work can remain unavailable for another attempt. Choose it deliberately; do not keep increasing it to hide an unexplained processing slowdown.
Separate queue limits from function capacity
Official distinction: maximum concurrency is configured per SQS mapping; reserved concurrency belongs to the function. AWS advises enough reserved capacity for the sum of mapping maxima. FIFO concurrency is also bounded by available message groups. Provisioned polling mode uses poller limits and cannot be combined with the maximum-concurrency setting.
Original capacity scenario: queues Orders and Notifications share one function. Their mapping maxima are 8 and 6, while function reserved concurrency is 10. The combined request for 14 slots exceeds the function's configured capacity. Naming only the Orders limit misses contention with Notifications.
Possible changes depend on the requirement: increase the function budget if account and downstream capacity allow, lower the mapping limits, or separate workloads needing independent protection. None is automatically correct without the traffic and failure assumptions.
Now suppose the Orders queue is FIFO and active work belongs to three message groups. A mapping maximum of 8 does not create eight independent ordered streams. Explain why the grouping choice can dominate the capacity discussion.
Finally, concurrency is not a request-per-second limit. Under an illustrative one-call-at-a-time workload, ten concurrent calls lasting half a second imply roughly twenty completions per second at steady state. If duration changes, so does that estimate. A strict downstream rate limit may require an additional rate-control mechanism.
Keep partial acknowledgment separate from idempotency
Partial reporting reduces unnecessary retries caused by another record's failure. It does not make an external payment, email, or database mutation exactly once.
Editorial failure scenario: A's downstream write commits, then the function stops before returning a usable response. On redelivery, the business destination must recognize whether A's operation already happened. A message-level failure list cannot retroactively make that earlier commit and response atomic.
Choose a business identity whose meaning survives the retries you intend to tolerate. Explain concurrent duplicate requests, retention of deduplication evidence, and what happens when the downstream result is uncertain. For that separate design problem, continue with One Order, Two Charges: Idempotency in SQS and Kafka.
During an incident, distinguish a handler exception, an item-level failure, a function throttle, and a business duplicate. Grouping all four under “Lambda errors” makes it harder to select the right repair.
Sources and Further Reading
- Using Lambda with Amazon SQS: polling, invocation, and duplicate delivery.
- Handling SQS event-source errors: partial responses and FIFO guidance.
- Creating an SQS event source mapping: visibility and function-timeout configuration.
- SQS event-source scaling: mapping concurrency, reserved capacity, and polling modes.
Sources checked September 10, 2026. Python control-flow tests ran locally; no AWS resources were deployed for this article.