Stacktape
Stacktape


DynamoDB Tables



Amazon DynamoDB is a serverless NoSQL key-value and document database that delivers single-digit millisecond performance at any scale. It's a fully managed, multi-active, durable database that is replicated across multiple Availability Zones.

Stacktape's DynamoDbTable resource provides a simple abstraction for provisioning and configuring Amazon DynamoDB tables.

When to use DynamoDB

Advantages

  • Performance at scale: DynamoDB provides consistent, single-digit millisecond response times at any scale. You can build applications with virtually unlimited throughput and storage.
  • Auto-scalable: DynamoDB supports auto-scaling of both read/write capacity and storage, so you don't have to worry about capacity planning.
  • Fine-grained access control: You can manage access to your DynamoDB tables using IAM roles and policies.
  • Connection-less: Your application connects to DynamoDB via an API, so you don't have to manage a connection pool.
  • Pay-per-request pricing: DynamoDB has a "pay-as-you-go" pricing model. If there's no load on your database, it's essentially free.

Disadvantages

  • Unfamiliar data modeling: If you're used to relational databases, DynamoDB's NoSQL data modeling can take some getting used to.
  • Proprietary: DynamoDB is a proprietary AWS database, which can lead to vendor lock-in.
  • Not as feature-rich as other databases: DynamoDB is more of a data store than a fully-featured database like Postgres or MongoDB. For a detailed comparison, refer to this MongoDB vs. DynamoDB article (which is arguably biased).

Basic Usage

The following example defines a simple DynamoDB table.

resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: id
type: string
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
environment:
- name: TABLE_NAME
value: $ResourceParam('myDynamoDbTable', 'name')
connectTo:
- myDynamoTable

You can connect a Lambda function to the table to read and write data:

import { DynamoDB } from '@aws-sdk/client-dynamodb';
const dynamoDb = new DynamoDB({});
export default async (event, context) => {
// Put item to the table
await dynamoDb.putItem({
Item: { id: { S: 'my_id_1' }, writeTimestamp: { S: new Date().toLocaleTimeString() } },
TableName: process.env.TABLE_NAME
});
// Get item from the table
const item = await dynamoDb.getItem({
Key: { id: { S: 'my_id_1' } },
TableName: process.env.TABLE_NAME
});
};

Primary Key

  • Primary key uniquely identifies each item in the table
  • Two different kinds of primary keys are supported:
    • simple primary key - you only specify partitionKey
    • composite primary key - you specify both partitionKey and sortKey
  • Primary key specification cannot be modified during updates (after the table is created).
  • The attribute must be top-level (not nested) field.
  • Each document saved to the table must contain the primary key attribute(s).
  • To learn more about primary keys, refer to AWS docs

Every item in a DynamoDB table is uniquely identified by a primary key. There are two types of primary keys:

  • Partition key: A simple primary key, composed of one attribute. DynamoDB uses the partition key's value as input to an internal hash function. The output from the hash function determines the partition (physical storage internal to DynamoDB) in which the item will be stored.
  • Partition key and sort key (composite primary key): All items with the same partition key value are stored together, in sorted order by the sort key value.
DynamoDbTablePrimaryKey  API reference
partitionKey
Required
sortKey

This example shows a table with a composite primary key:

resources:
myDynamoTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: this_attribute_will_be_partition_key
type: string
sortKey:
name: this_attribute_will_be_sort_key
type: number

Provisioned Throughput

  • When you specify provisionedThroughput, the table will run in the provisioned mode and you need to specify read and write throughput for your table.
  • This can give you cost predictability and lower costs, but your table might not be able to handle an unpredictable load.
  • If provisionedThroughput is not configured, the table runs and is billed in an on-demand mode. This means you are only paying for what you use.
  • To learn more about differences between provisioned and on-demand modes, refer to AWS docs

DynamoDB has two capacity modes for processing reads and writes on your tables: on-demand and provisioned.

  • On-demand: This is the default mode. You pay per request, which is suitable for unpredictable workloads.
  • Provisioned: You specify the number of reads and writes per second that you require for your application. This is best for predictable traffic.

You can also configure auto-scaling for provisioned throughput to automatically adjust your table's capacity based on traffic.

DynamoDbProvisionedThroughput  API reference
readUnits
Required
writeUnits
Required
writeScaling
readScaling
resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: this_attribute_will_be_id
type: string
provisionedThroughput:
readUnits: 4
writeUnits: 4

Throughput Scaling

  • Even in provisioned mode, you can configure throughput scaling based on load.
  • The table throughput scales up or down once the specified thresholds are met.
  • Compared to on-demand mode (default, if you don't specify provisionedThroughput), you have more control of how your table will scale and can save costs. However, your table might not be able to scale enough for an unpredictable load.
  • To learn more, refer to this detailed AWS article

The following example shows how to configure auto-scaling for read and write capacity.

resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: this_attribute_will_be_id
type: string
provisionedThroughput:
readUnits: 4
writeUnits: 4
readScaling:
minUnits: 4
maxUnits: 10
keepUtilizationUnder: 80
DynamoDbReadScaling  API reference
minUnits
Required
maxUnits
Required
keepUtilizationUnder
Required
DynamoDbWriteScaling  API reference
minUnits
Required
maxUnits
Required
keepUtilizationUnder
Required

Point-in-Time Recovery

  • Point-in-time recovery enables you to restore table to any point in time during the last 35 days
  • The point-in-time recovery process always restores the data to a new table. You can restore data to the same table.
  • Enabling point-in-time recovery can result in additional charges. To learn more, refer to AWS DynamoDB pricing

Point-in-time recovery (PITR) helps protect your tables from accidental write or delete operations. With PITR, you can restore that table to any point in time during the last 35 days.

resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: this_attribute_will_be_id
type: string
enablePointInTimeRecovery: true

Item-Change Streaming

You can capture a time-ordered sequence of item-level modifications in any DynamoDB table and store this information in a log for up to 24 hours. Applications can access this log and view the data items as they appeared before and after they were modified, in near-real time. This is called DynamoDB Streams.

Streams can be consumed by functions and batch jobs.

You must configure the stream type, which determines what information is written to the stream when an item in the table is modified. Allowed values are:

  • KEYS_ONLY: Only the key attributes of the modified item.
  • NEW_IMAGE: The entire item as it appeared after it was modified.
  • OLD_IMAGE: The entire item as it appeared before it was modified.
  • NEW_AND_OLD_IMAGES: Both the new and the old images of the item.
resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: this_attribute_will_be_id
type: string
streamType: NEW_AND_OLD_IMAGES

Access Control

DynamoDB uses IAM to control who can access the table. To interact with a DynamoDB table, your compute resources must have sufficient permissions. You can grant these permissions in two ways:

  1. List the table in the connectTo array of your compute resource. Stacktape will automatically grant the necessary permissions.
  2. Configure iamRoleStatements on your compute resource to define a custom policy.

Using connectTo is the recommended approach. Here's an example:

resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: id
type: string
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
environment:
- name: TABLE_NAME
value: $ResourceParam('myDynamoDbTable', 'name')
connectTo:
- myDynamoDbTable

If you need more fine-grained control, you can use iamRoleStatements:

resources:
myDynamoDbTable:
type: dynamo-db-table
properties:
primaryKey:
partitionKey:
name: id
type: string
myFunction:
type: function
properties:
packaging:
type: stacktape-lambda-buildpack
properties:
entryfilePath: path/to/my/lambda.ts
environment:
- name: TABLE_NAME
value: $ResourceParam('myDynamoDbTable', 'name')
iamRoleStatements:
- Resource:
- $ResourceParam('myDynamoDbTable', 'Arn')
Effect: 'Allow'
Action:
- 'dynamodb:Get*'
- 'dynamodb:Query'
- 'dynamodb:Scan'
- 'dynamodb:Delete*'
- 'dynamodb:Update*'
- 'dynamodb:PutItem'

Pricing

You are charged for:

  • Read and Write operations:
    • PROVISIONED mode:
      • You configure how much read/write capacity table has at any moment:
      • WCU (write capacity unit) - $0.00065 - $0.000975 per WCU per hour
      • RCU (read capacity units - $0.00013 - $0.000195 per RCU per hour
      • To learn more, refer to AWS pricing page
    • ON DEMAND mode
      • Pay as you go
      • $1.25 - $1.875 per million write request units
      • $0.25- $0.375 per million read request units
      • To learn more, refer to AWS pricing page
  • Storage:
    • First 25 GB stored per month is free
    • $0.25 - $0.375 per GB-month thereafter
  • Continuous backup:
    • Applies when point-in-time-recovery is enabled
    • $0.20 -$0.30 per GB-month
  • Data transfer:
    • IN transfer: free
    • OUT to AWS services in the same region: free
    • OUT to internet: first 1 GB free, then $0.09 -$0.15 per GB

FREE TIER (eligible for first 12 months):

  • 25 GB of Storage
  • 25 provisioned Write Capacity Units (WCU)
  • 25 provisioned Read Capacity Units (RCU)
  • Enough to handle up to ~200M requests per month.

Referenceable parameters

The following parameters can be easily referenced using $ResourceParam directive directive.

To learn more about referencing parameters, refer to referencing parameters.

name
  • AWS (physical) name of the table

  • Usage: $ResourceParam('<<resource-name>>', 'name')
arn
  • Arn of the table

  • Usage: $ResourceParam('<<resource-name>>', 'arn')
streamArn
  • Arn of DynamoDb stream (available only if streamType is configured)

  • Usage: $ResourceParam('<<resource-name>>', 'streamArn')

API Reference

DynamoDbTable  API reference
type
Required
properties.primaryKey
Required
properties.provisionedThroughput
properties.enablePointInTimeRecovery
properties.streamType
properties.secondaryIndexes
overrides

Contents