Lambda Powertools idempotency and Sume's Idempotency-Key: use both

Powertools idempotency guards your Lambda handler; Sume's Idempotency-Key guards the paid submit. How they differ, and how to derive one key from an order id.

5 min readSume
All posts

Yes, use both, because they guard different things. Powertools for AWS Lambda's idempotency utility stops your handler from running twice for the same event, while Sume's Idempotency-Key header stops a retried paid submit from creating a second job. Derive the Sume key from your own business id, never from the invocation, so that a handler that does run twice still sends the same key.

The Powertools facts come from its idempotency utility page (read 2026-10-11). The Sume facts come from Jobs and results, Generation admission and the submit code on main.

What does each layer protect?

The two keys live in different places and expire on different clocks, which is why one cannot replace the other.

Powertools values from the AWS page (read 2026-10-11); Sume values from docs.sume.com and the API source.
Powertools idempotencySume Idempotency-Key
ProtectsYour Lambda handler and its return valueThe paid submit call to api.sume.com
KeyFunction name plus a hash of the payload, or fields picked with event_key_jmespathA string you send: 255 printable characters or fewer
Stored inA DynamoDB table (INPROGRESS, COMPLETE, EXPIRED)Sume, on the job record
Default lifetimeexpires_after_seconds is 3600 (1 hour)Not stated in the docs I read
Same key, changed inputpayload_validation_jmespath raises IdempotencyValidationError409 idempotency_conflict

Which key should the handler send to Sume?

Build it from the thing a human would call the order: an order id plus a version, or a render slot such as a date. Three rules keep it safe.

  • Do not use a fresh UUID per invocation. A re-run then sends a new key and bills a second job.
  • Do not reuse a key for a different request. Sume answers 409 idempotency_conflict when a key meets a different operation or payload, and the error details hand back the job_id, job_status, status_url and result_url of the job that already owns the key, so adopt that job instead of minting a new key.
  • Hash long business keys. The limit is 255 printable characters, and a longer or control-character key is rejected with a 400.

What happens when the Lambda times out mid-submit?

This is the case the two layers were made for. Powertools marks the record INPROGRESS, and if you call register_lambda_context(), a second invocation that arrives after the first one's remaining time has passed treats the record as expired and runs the handler again. If the first run had already reached Sume, the second run sends the same business key, and Sume returns the original job instead of creating another. Without the Sume key, that re-run is a second paid clip.

The same logic covers the 1 hour default. If an event is redelivered after the Powertools record expired, the handler runs again as if new. A key built from the order id still resolves to the first job, as long as Sume still holds that key, which is why the lifetime row above says "not stated" and why you should also keep the job id in your own table.

What should the handler return, and what about 429s?

Return the job id (and status_url) from the idempotent function, not the finished video. Powertools stores that return value, so a replay inside its window gives the same id back, and the video itself arrives later by polling GET /v1/jobs/{id}/status or by a signed webhook. Do not wait for a video inside the handler; the jobs docs call a client timeout a wait that ends, not a job that stops.

One exception to "same key, same job" is worth knowing. When a submit is refused with 429 queue_full, the generation docs say to retry with the same idempotency key once capacity opens. In the current submit code, a job refused at queue admission is the one case where the key is freed, so that retry creates a fresh job rather than returning the dead one. A 429 rate_limited is different: back off using retry-after.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume