Docs / Strand / connectors/aws-dynamodb
AWS DynamoDB Connector
Direction: Read / Write | Type: aws.dynamodb
Read, write, and query items in Amazon DynamoDB tables from your Strand workflows.
Prerequisites#
You need AWS credentials with DynamoDB permissions. Here's how to set them up:
- Sign in to the AWS Management Console and navigate to IAM
- Create a new IAM user or use an existing one
- Attach a policy with the permissions listed in Required Permissions below
- Under Security credentials, create an Access key
- Copy the Access Key ID and Secret Access Key
Required Permissions#
The IAM user or role must have the following permissions:
| Operation | Required IAM Permissions |
|---|---|
| Put Item | dynamodb:PutItem |
| Get Item | dynamodb:GetItem |
| Query | dynamodb:Query |
| Scan | dynamodb:Scan |
All operations also require dynamodb:DescribeTable.
Tip: Scope the IAM policy to specific table ARNs (e.g., arn:aws:dynamodb:us-east-1:123456789:table/my-table) to follow the principle of least privilege.
Connector Setup#
Create an AWS DynamoDB connector from the Connectors page.
Configuration Fields#
| Field | Required | Description |
|---|---|---|
| Name | Yes | Friendly name (e.g., "Production DynamoDB") |
| Authentication Type | No | Uses explicit AWS access-key credentials (the fields below). |
| Region | Yes | AWS region where your DynamoDB tables reside (e.g., us-east-1) |
| Endpoint URL | No | Custom endpoint for a self-managed target or an AWS VPC endpoint. Leave empty for AWS. |
| Access Key ID | Conditional | IAM user access key ID (encrypted at rest). Required when Authentication Type is api_key |
| Secret Access Key | Conditional | IAM user secret access key (encrypted at rest). Required when Authentication Type is api_key |
| Default Table Name | No | Default DynamoDB table name (can be overridden at node level) |
| Timeout | No | API request timeout in seconds (default: 30) |
| Description | No | Optional description for reference |
Operations#
Put Item#
Write a single item to a DynamoDB table.
| Field | Required | Description |
|---|---|---|
| Table Name | Yes | Name of the DynamoDB table (e.g., orders) |
| Item (JSON) | No | JSON object representing the item to write. If left empty, the incoming event payload is used as the item. Must include the table's primary key attributes. |
Use plain JSON; values are auto-marshaled into DynamoDB types by the resource-level Table API. Do not wrap values in typed JSON ({"S": ...}, {"N": ...}).
Example: Insert an order record
{
"order_id": "{{ payload.order_id }}",
"customer_email": "{{ payload.email }}",
"total": {{ payload.total }},
"status": "pending",
"created_at": "{{ payload.timestamp }}"
}
Get Item#
Retrieve a single item by its primary key.
| Field | Required | Description |
|---|---|---|
| Table Name | Yes | Name of the DynamoDB table |
| Key (JSON) | Yes | JSON object with the primary key attribute(s) |
Example: Fetch an order by ID
{
"order_id": "{{ payload.order_id }}"
}
Query#
Query items using a key condition expression. Returns items that match the partition key and optional sort key condition.
| Field | Required | Description |
|---|---|---|
| Table Name | Yes | Name of the DynamoDB table |
| Key Condition Expression | Yes | Key condition using DynamoDB expression syntax (e.g., order_id = :id) |
| Expression Attribute Values (JSON) | Yes | JSON object mapping expression placeholders to values. Use plain values; DynamoDB types are auto-detected. |
| Limit | No | Maximum number of items to return (default: 25) |
| Index Name | No | Name of a Global or Local Secondary Index to query |
Example: Query orders by customer
- Key Condition Expression:
customer_id = :cid AND created_at > :since - Expression Attribute Values:
{
":cid": "{{ payload.customer_id }}",
":since": "2026-01-01T00:00:00Z"
}
Scan#
Scan the entire table with an optional filter expression. Use sparingly on large tables.
| Field | Required | Description |
|---|---|---|
| Table Name | Yes | Name of the DynamoDB table |
| Filter Expression | No | Filter expression to narrow results (e.g., status = :s) |
| Expression Attribute Values (JSON) | No | JSON object mapping expression placeholders to values. Use plain values; DynamoDB types are auto-detected. |
| Limit | No | Maximum number of items to return (default: 25) |
Example: Scan for pending orders
- Filter Expression:
status = :status - Expression Attribute Values:
{
":status": "pending"
}
Output#
Put Item Output#
{
"success": true,
"status": "completed",
"data": {
"table": "orders",
"item_keys": {"note": "item stored"}
},
"service": "aws.dynamodb",
"operation": "put_item"
}
Get Item Output#
Items are returned as plain JSON; DynamoDB types are converted automatically.
{
"success": true,
"status": "completed",
"data": {
"table": "orders",
"item": {
"order_id": "ORD-12345",
"customer_email": "alice@example.com",
"total": 149.99,
"status": "pending",
"created_at": "2026-02-18T10:00:00Z"
}
},
"service": "aws.dynamodb",
"operation": "get_item"
}
When no item matches, status is not_found and data.item is null.
Key fields for subsequent nodes:
{{ steps.node_a1b2c3d4.output_payload.data.item }}: The retrieved item{{ steps.node_a1b2c3d4.output_payload.data.item.status }}: A specific attribute value
Query Output#
{
"success": true,
"status": "completed",
"data": {
"table": "orders",
"items": [
{
"order_id": "ORD-12345",
"customer_id": "CUST-001",
"total": 149.99,
"status": "shipped"
}
],
"count": 1,
"scanned_count": 1,
"last_evaluated_key": null,
"has_more": false
},
"service": "aws.dynamodb",
"operation": "query"
}
Key fields for subsequent nodes:
{{ steps.node_a1b2c3d4.output_payload.data.items }}: Array of matching items{{ steps.node_a1b2c3d4.output_payload.data.count }}: Number of items returned{{ steps.node_a1b2c3d4.output_payload.data.has_more }}:trueif more items remain{{ steps.node_a1b2c3d4.output_payload.data.last_evaluated_key }}: Pagination cursor; pass it back via Start Key to fetch the next page
Scan Output#
{
"success": true,
"status": "completed",
"data": {
"table": "orders",
"items": [
{
"order_id": "ORD-12345",
"status": "pending",
"total": 149.99
}
],
"count": 1,
"scanned_count": 50,
"last_evaluated_key": null,
"has_more": false
},
"service": "aws.dynamodb",
"operation": "scan"
}
Errors#
| Error | Meaning |
|---|---|
| AWS access_key_id is required | Access key ID not configured in connector. |
| AWS secret_access_key is required | Secret access key not configured in connector. |
| Table name is required | No table name specified in the operation. |
| Key is required | No key provided for a Get Item operation. |
| Key condition expression is required | No key condition specified for a Query operation. |
| ResourceNotFoundException | The specified table does not exist in the configured region. |
| ValidationException | Invalid item structure, expression syntax, or missing required key attributes. |
| ConditionalCheckFailedException | A condition expression was not satisfied. |
| ProvisionedThroughputExceededException | Table throughput limit exceeded. Retry with backoff or increase capacity. |
| AccessDeniedException | The IAM user lacks the required DynamoDB permissions. |
| UnrecognizedClientException | Invalid AWS access key ID. |
| SignatureDoesNotMatch | Secret access key is incorrect. |
Example Workflow#
- Create Connector with your AWS credentials and region
us-east-1 - Put item to store an incoming order:
- Table Name:
orders - Item:
{"order_id": "{{ payload.order_id }}", "customer_id": "{{ payload.customer_id }}", "status": "received"}
- Query to check for the customer's recent orders:
- Key Condition Expression:
customer_id = :cid - Expression Attribute Values:
{":cid": "{{ payload.customer_id }}"} - Limit:
10
- Send notification via a downstream connector with the order count:
- Message:
Customer {{ payload.customer_id }} now has {{ steps.query_orders.output_payload.data.count }} recent orders
Limitations#
- Single item writes: Each Put Item operation writes one item. For batch writes, use multiple workflow nodes.
- Item size: Individual items are limited to 400 KB by AWS.
- Scan performance: Full table scans consume significant read capacity on large tables. Prefer Query operations with proper key conditions.
- Plain JSON only: Items, keys, and expression values use plain JSON (e.g.,
"order_id": "ORD-123","total": 149.99). DynamoDB types are auto-detected and marshaled for you, so do not use typed JSON ({"S": ...},{"N": ...}). - Transactions: Transactional writes and reads are not currently supported.
- Pagination: Results exceeding the limit are not automatically paginated. Use the returned
last_evaluated_keyin subsequent requests if needed.
Tendrl