dynobase-icon
Dynobase

DynamoDB Triggers with Lambda: Setup, Examples and Retries

Daniel Galati

Written by Daniel Galati

Last updated: October 23rd, 2026

Investigating throttling or capacity? Dynobase shows a table's CloudWatch metrics next to its data, tails DynamoDB Streams and can refresh results automatically. Metrics and streams in Dynobase

A DynamoDB trigger is a Lambda event source mapping that reads a table's DynamoDB Stream and invokes a function with batches of item changes. It runs after the database write succeeds, so it cannot reject or roll back that write. Lambda can deliver a record more than once; reliable triggers combine idempotent processing, bounded retries and a recovery destination.

What runs when an item changes?

The stream captures INSERT, MODIFY and REMOVE events. Lambda polls the stream, batches records, invokes your function and advances its checkpoint after successful processing. The writer does not wait for the function. A write that leaves the item unchanged produces no stream record.

Use triggers for notifications, search indexing, audit exports and derived data. Validate a write in the application or with a DynamoDB condition expression when it must be rejected before storage. See how DynamoDB Streams work for shard behavior, record retention and the full event format.

Enable the stream and prepare permissions

Choose a stream view that contains the data your handler needs:

ViewData available to the handler
KEYS_ONLYPrimary key attributes
NEW_IMAGEItem after an insert or update
OLD_IMAGEItem before an update or deletion
NEW_AND_OLD_IMAGESBoth versions when applicable

An insert never has an old image; a delete never has a new one. A MODIFY record contains both only when you selected both. The examples use a People table with a string partition key named PersonId.

For a table without an active stream:

Use the table's Region for every command. Changing a view requires replacing the stream, which changes its ARN; reconnect mappings and stream policies afterward.

The function's execution role needs dynamodb:DescribeStream, dynamodb:GetShardIterator, dynamodb:GetRecords and dynamodb:ListStreams, plus CloudWatch Logs access. The AWS managed policy AWSLambdaDynamoDBExecutionRole supplies baseline permissions; a custom policy can restrict stream actions to the intended resource. These are runtime permissions, separate from the deployment identity's permission to create mappings and pass the execution role.

If your handler calls another service, grant that operation separately. A failure queue requires sqs:SendMessage on its ARN. An S3 failure destination requires bucket/object permissions and, with a customer managed key, the applicable KMS permission.

Create the Lambda trigger

Create a function named people-stream-handler, using nodejs24.x for the JavaScript example below or python3.13 for Python. Package the handler and its dependencies, and configure the execution role before adding the trigger.

In the Lambda console, open the function, choose Add trigger, select DynamoDB and the table, and configure the starting position and batch settings. Review the advanced retry and failure settings rather than accepting unlimited retries automatically.

The equivalent AWS CLI v2 command uses an existing standard SQS queue for failure metadata. Replace its example account ID and Region:

These retry and age values are example operating choices, not universal defaults. Keep the mapping UUID from the response. Use get-event-source-mapping --uuid to inspect status and update-event-source-mapping --uuid to change it.

CloudFormation setup

This deployable template creates a table, log-only Python function, role, failure queue and mapping. Replace the inline handler with your packaged business logic for a real service:

AWS CDK with Python

Within a CDK v2 application, this alternative creates the same relationship. Put the Python handler shown below in lambda/people/index.py and package its dependencies in that asset directory:

Event source mapping settings

SettingDefault or supported rangePractical effect
BatchSizeDefault 100; up to 10,000 recordsInvocation payload also cannot exceed 6 MB, including record metadata
MaximumBatchingWindowInSecondsDefault 0; up to 300 secondsTrades lower invocation count for additional delay
StartingPositionTRIM_HORIZON or LATESTOldest retained records or newly arriving records
ParallelizationFactorDefault 1; up to 10Concurrent batches per shard, with ordering preserved for each item's changes
MaximumRetryAttemptsDefault -1; configurable retry capPrevents a permanently failing invocation from blocking progress indefinitely
MaximumRecordAgeInSecondsDefault -1; configurable age capDiscards records that are too old; does not extend stream retention
BisectBatchOnFunctionErrorDefault falseSplits failed batches to isolate a problematic record
FunctionResponseTypesEnable ReportBatchItemFailuresAllows the handler to identify the first failed sequence number
DestinationConfigNo destination by defaultSends discarded-invocation details to a recovery destination
FilterCriteriaNo filtering by defaultRemoves unwanted records before invocation
EnabledDefault truePauses or resumes polling without deleting the mapping

AWS documents the mapping parameters separately from general Lambda asynchronous invocation options. Configure retry handling on the mapping, not just a function-level asynchronous dead-letter queue.

TRIM_HORIZON is usually the safer initial position: mapping creation can take time, and LATEST can miss writes during that startup interval. The new DynamoDB Streams timestamp-start capability is available to supported stream readers, but the Lambda DynamoDB mapping documentation still lists TRIM_HORIZON and LATEST. Do not assume every consumer accepts AT_TIMESTAMP.

Handle inserts, updates, deletes and TTL

This abbreviated insert event keeps Keys and NewImage consistent:

For a name update, eventName becomes MODIFY, OldImage.FirstName.S is John, and NewImage.FirstName.S is James. For deletion, eventName is REMOVE and only the old image is present. All events retain the key attributes.

JavaScript handler using SDK v3

Save as index.mjs, with handler index.handler, and bundle @aws-sdk/util-dynamodb. This handler logs the insert, name change or deletion and stops at the first failed record. Replace the log operation with an awaited, idempotent side effect:

This example logs names to demonstrate the images. In production, log event IDs and approved diagnostic fields rather than personal data or complete item images. SDK v3 replaces the unsupported aws-sdk v2 package.

Python handler with boto3

Boto3's TypeDeserializer converts DynamoDB JSON values; numeric attributes become Decimal. This version handles the same event types:

TTL deletes

A TTL expiration produces a REMOVE event with userIdentity.type equal to Service and userIdentity.principalId equal to dynamodb.amazonaws.com. Use those fields to distinguish expiration from an application delete. On global tables, only the Region that performed expiration marks the event this way. TTL deletion is asynchronous, typically within a few days; it is not a precise scheduler. See DynamoDB TTL.

Filter events before invoking Lambda

For a function that handles only inserts, save this object as filters.json:

To match a particular new name, the pattern itself would be:

Put that pattern into the mapping's string-valued Pattern field. Filtering uses DynamoDB's typed representation, not the plain objects produced by unmarshall. Numeric filter operators do not work on DynamoDB number strings. Filters cannot compare old and new values dynamically; compare them in your handler when you need a transition check.

Unmatched records are skipped, not saved for later. Changing a filter does not rewind a mapping. AWS's DynamoDB event filtering documentation covers the supported pattern structure.

Retries, partial batches and recovery

Without partial responses, throwing an error retries the whole batch, including records that already succeeded. With ReportBatchItemFailures, return the failed record's sequence number, not eventID. Lambda resumes from the lowest failed sequence number. Both handlers stop at the first failure so they do not perform later work that would immediately be replayed.

Bisecting helps isolate invocation failures; splitting a batch does not consume the retry quota. Retry-count limits apply to errors returned by an invoked function. Pre-invocation failures, such as throttling, are governed by record age and retention rather than that same function-error retry count.

When retry or age limits are reached, Lambda discards records and advances. A standard SQS or SNS failure destination receives invocation metadata and stream sequence information, not the full original batch. Recover those records before the stream's 24-hour retention expires. An S3 destination retains the full invocation payload, which supports later investigation and replay. Follow the failure-destination configuration and monitor delivery failures too.

Make downstream operations idempotent. For a database projection, store and conditionally compare a business version. For an external API, pass a stable idempotency key supported by that API. Merely recording an event ID before sending a notification can lose the notification if the function crashes between those steps.

Cross-account triggers, scaling and monitoring

Lambda supports a DynamoDB stream in another account through a resource-based policy on that stream. The function and stream must still be in the same Region. Grant the function execution role stream-read permission in its own account and allow that role in the stream policy. Follow AWS's cross-account Lambda setup. Recreated streams need a policy on their new ARN.

Design for up to two readers per shard on a single-Region table; AWS recommends one for global tables. Multiple mappings do not provide unlimited fan-out. Use one consumer to publish notifications through SNS, or use Kinesis Data Streams when the consumer requirements justify it.

Monitor IteratorAge, Lambda errors, duration, throttles and destination-delivery failures. Rising iterator age means processing is falling behind; investigate failures and downstream latency before raising concurrency. Avoid writing back to the source item without a filter or condition that prevents an invocation loop.

Standard Lambda trigger reads from DynamoDB Streams are free, while Lambda execution and downstream services are billed. Lambda Managed Instances are an exception to that free stream-read treatment. Test replayed records, missing images, malformed attributes, permission failures and a deliberately failing record before enabling production traffic.

Frequently Asked Questions

Does DynamoDB have triggers?

Yes. A Lambda event source mapping reads DynamoDB Streams and invokes your function after item changes. It is asynchronous and cannot roll back the original write.

Can DynamoDB trigger Step Functions?

Yes, through an integration such as EventBridge Pipes with a DynamoDB stream source and a Step Functions target, or through a Lambda handler that starts an execution. A custom Lambda bridge is not always required.

Can I configure multiple DynamoDB triggers?

Yes, but design for up to two concurrent readers per shard on single-Region tables and one recommended reader on global tables. Fan out downstream if you need more consumers.

Why is my DynamoDB trigger processing records twice?

Lambda event source mappings deliver at least once. Retries can repeat successful work, so use partial batch responses and make downstream side effects idempotent.

Can a Lambda function read a DynamoDB stream in another account?

Yes, with permissions on its execution role and a resource-based policy on the stream. The function and stream still need to be in the same Region.

Why is my trigger not receiving updates?

Check that the mapping is enabled, uses the current stream ARN, has read permissions and has a matching filter. Also inspect mapping status, Lambda throttles and IteratorAge; an unchanged item write produces no event.

Dynobase is a Professional GUI Client for DynamoDB

Start your 7-day free trial today

Product Features

Download
/
Pricing
/
Member Portal
/
Privacy
/
EULA
/
Twitter
© 2026 Dynobase