Docs / Strand / connectors/aws-dynamodb
AWS DynamoDB Connector
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 | api_key (default) for explicit credentials, role to use the host's IAM role / default credential chain |
| 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 |
| Role ARN | Conditional | Your IAM role ARN for cross-account access via STS AssumeRole. Required when Authentication Type is role. The role must trust the Tendrl AWS account. |
| External ID | No | External ID for STS AssumeRole (encrypted). Recommended with role auth to prevent confused-deputy attacks. |
| Timeout | No | API request timeout in seconds (default: 30) |
| Description | No | Optional description for reference |
With role authentication you do not store static access keys; Strand authenticates using the host's default credential chain (EC2 instance profile, ECS task role, or environment credentials). You must still provide a Role ARN when creating the connector (the role should trust the Tendrl AWS account); an optional External ID hardens the trust policy.
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": "[email protected]",
"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(or useauth_type: "role"to leverage the host's IAM role) - 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