> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fjall.io/llms.txt
> Use this file to discover all available pages before exploring further.

# DynamoDB Table

> Add a serverless AWS DynamoDB table in Fjall with GSIs, streams, TTL, and point-in-time recovery.

## Overview

The `DynamoDBTable` construct creates an Amazon DynamoDB table with sensible defaults for serverless workloads. It supports on-demand and provisioned billing, global secondary indexes, streams, and point-in-time recovery.

## Import

```typescript theme={null}
import { DynamoDBTable } from "@fjall/components-infrastructure/lib/resources/aws/database/dynamodb";
```

## Basic Usage

```typescript theme={null}
const table = new DynamoDBTable(scope, "Sessions", {
  partitionKey: { name: "sessionId", type: "S" },
});
```

## Using the Database Factory

The recommended way to add DynamoDB to a Fjall application is through the `DatabaseFactory`:

```typescript theme={null}
import { DatabaseFactory } from "@fjall/components-infrastructure/lib/patterns/aws/database";

const cache = app.addDatabase(
  DatabaseFactory.build("Cache", {
    type: "DynamoDB",
    partitionKey: { name: "id", type: "S" },
  }),
);
```

## Properties

| Property                 | Type                                                                | Default             | Description                             |
| ------------------------ | ------------------------------------------------------------------- | ------------------- | --------------------------------------- |
| `partitionKey`           | `{ name: string, type: "S" \| "N" \| "B" }`                         | **Required**        | Partition key attribute                 |
| `sortKey`                | `{ name: string, type: "S" \| "N" \| "B" }`                         | --                  | Sort key attribute                      |
| `billingMode`            | `"PAY_PER_REQUEST" \| "PROVISIONED"`                                | `"PAY_PER_REQUEST"` | Billing mode                            |
| `readCapacity`           | `number`                                                            | --                  | Read capacity units (provisioned only)  |
| `writeCapacity`          | `number`                                                            | --                  | Write capacity units (provisioned only) |
| `globalSecondaryIndexes` | `DynamoDBGlobalSecondaryIndex[]`                                    | --                  | GSI definitions                         |
| `timeToLiveAttribute`    | `string`                                                            | --                  | TTL attribute name                      |
| `stream`                 | `"NEW_IMAGE" \| "OLD_IMAGE" \| "NEW_AND_OLD_IMAGES" \| "KEYS_ONLY"` | --                  | DynamoDB Streams mode                   |
| `pointInTimeRecovery`    | `boolean`                                                           | `true`              | Enable point-in-time recovery           |
| `encryption`             | `"AWS_OWNED" \| "AWS_MANAGED" \| "CUSTOMER_MANAGED"`                | `"AWS_OWNED"`       | Encryption type                         |
| `removalPolicy`          | `"DESTROY" \| "RETAIN" \| "SNAPSHOT"`                               | `"RETAIN"`          | What happens on stack deletion          |

### Key Types

Attribute types map to DynamoDB types:

| Type  | DynamoDB Type | Use For                 |
| ----- | ------------- | ----------------------- |
| `"S"` | String        | IDs, names, emails      |
| `"N"` | Number        | Timestamps, counters    |
| `"B"` | Binary        | Hashes, compressed data |

## Methods

| Method                     | Returns               | Description                         |
| -------------------------- | --------------------- | ----------------------------------- |
| `getTableName()`           | `string`              | Table name                          |
| `getTableArn()`            | `string`              | Table ARN                           |
| `getTableStreamArn()`      | `string \| undefined` | Stream ARN (if streams enabled)     |
| `getTable()`               | `ITable`              | CDK Table construct                 |
| `grantRead(grantee)`       | `Grant`               | Grant read access                   |
| `grantWrite(grantee)`      | `Grant`               | Grant write access                  |
| `grantReadWrite(grantee)`  | `Grant`               | Grant read and write access         |
| `grantFullAccess(grantee)` | `Grant`               | Grant full access (including admin) |
| `grantStreamRead(grantee)` | `Grant`               | Grant stream read access            |

## Examples

### Composite Key Table

```typescript theme={null}
const orders = app.addDatabase(
  DatabaseFactory.build("Orders", {
    type: "DynamoDB",
    partitionKey: { name: "customerId", type: "S" },
    sortKey: { name: "orderDate", type: "N" },
    pointInTimeRecovery: true,
  }),
);
```

### Table with Global Secondary Index

```typescript theme={null}
const users = app.addDatabase(
  DatabaseFactory.build("Users", {
    type: "DynamoDB",
    partitionKey: { name: "userId", type: "S" },
    globalSecondaryIndexes: [
      {
        indexName: "emailIndex",
        partitionKey: { name: "email", type: "S" },
        projectionType: "ALL",
      },
    ],
  }),
);
```

### Provisioned Throughput

```typescript theme={null}
const events = app.addDatabase(
  DatabaseFactory.build("Events", {
    type: "DynamoDB",
    partitionKey: { name: "pk", type: "S" },
    sortKey: { name: "sk", type: "S" },
    billingMode: "PROVISIONED",
    readCapacity: 100,
    writeCapacity: 50,
  }),
);
```

### With DynamoDB Streams

```typescript theme={null}
const audit = app.addDatabase(
  DatabaseFactory.build("AuditLog", {
    type: "DynamoDB",
    partitionKey: { name: "entityId", type: "S" },
    sortKey: { name: "timestamp", type: "N" },
    stream: "NEW_AND_OLD_IMAGES",
  }),
);

// Connect a Lambda to process stream events
processor.addDynamoDbEventSource(audit);
```

### TTL for Automatic Expiry

```typescript theme={null}
const sessions = app.addDatabase(
  DatabaseFactory.build("Sessions", {
    type: "DynamoDB",
    partitionKey: { name: "sessionId", type: "S" },
    timeToLiveAttribute: "expiresAt",
  }),
);
```

## Connecting to Compute

Grant permissions to Lambda or ECS services:

```typescript theme={null}
// Read-only access
table.grantRead(readerLambda);

// Read-write access
table.grantReadWrite(apiService);

// Stream processing
table.grantStreamRead(processorLambda);
```

## CloudFormation Outputs

Each DynamoDB table exports:

| Output               | Description             |
| -------------------- | ----------------------- |
| `{id}TableName`      | Table name              |
| `{id}TableArn`       | Table ARN               |
| `{id}TableStreamArn` | Stream ARN (if enabled) |

## Next Steps

<CardGroup cols={2}>
  <Card title="Database Factory" icon="industry" href="/patterns/database-factory">
    Create databases via the factory pattern
  </Card>

  <Card title="Lambda Function" icon="bolt" href="/resources/compute/lambda-function">
    Process DynamoDB streams with Lambda
  </Card>
</CardGroup>
