DynamoDB ORM for TypeScript

Model DynamoDB items as plain classes.

Decorator-first mapping for single-table designs. Typed entities, relationship loading, and CRUD primitives without a heavy framework.

npm install orm-dynamodb

Demo

See it in action.

A quick walkthrough of entity decorators, inserts, queries, and link loading.

Features

Everything you need, nothing you don't.

Keep DynamoDB access close to your domain model. Entities declare keys, transformations, and links in one place, while BaseEntity handles the repetitive SDK calls.

Type-safe decorators

Entity and key decorators with full TypeScript inference on every attribute.

Linked objects

Lazy-load related entities with @LinkObject and @LinkArray.

Explicit timestamps

Map createdAt and updatedAt yourself with @ToDbModel when you need them.

Serialization hooks

Custom @ToDbModel and @FromDbModel for type coercions like Date.

Query helpers

Built-in patterns for begins-with, between, and other sort key queries.

AWS SDK v3

Explicit client config — bring your own DynamoDBClient.

Quick start

Configure once, then work with entities.

Pass a DynamoDBClient to BaseEntity.configure(), decorate your classes, and start reading and writing items.

entity.ts
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import {
  BaseEntity, Entity, FromDbModel,
  HashKeyValue, LinkObject, SortKeyValue, ToDbModel,
} from 'orm-dynamodb';

// Configure once at app startup
BaseEntity.configure(new DynamoDBClient({ region: 'us-east-1' }));

@Entity('content', 'pk', 'sk')
class Author extends BaseEntity {
  @HashKeyValue
  get hashKey() { return 'AUTHOR'; }

  @SortKeyValue
  get sortKey() { return this.authorId; }

  authorId: string;
  displayName: string;

  constructor(authorId = '', displayName = '') {
    super();
    this.authorId = authorId;
    this.displayName = displayName;
  }
}

@Entity('content', 'pk', 'sk')
class Post extends BaseEntity {
  @HashKeyValue
  get hashKey() { return 'POST'; }

  @SortKeyValue
  get sortKey() { return this.slug; }

  slug: string;
  title: string;
  publishedAt: Date | null;

  @LinkObject(Author)
  author: Author | undefined;

  constructor(slug = '', title = '', publishedAt: Date | null = null) {
    super();
    this.slug = slug;
    this.title = title;
    this.publishedAt = publishedAt;
  }

  @ToDbModel
  static toDbModel(post: Post) {
    return {
      publishedAt: post.publishedAt ? post.publishedAt.toISOString() : null,
    };
  }

  @FromDbModel
  static fromDbModel(item: { publishedAt?: string | null }) {
    return {
      publishedAt: item.publishedAt ? new Date(item.publishedAt) : null,
    };
  }
}

Setup

Two tsconfig flags required.

Enable these in your tsconfig.json before using decorators.

experimentalDecorators

Enables the @Decorator syntax used by all entity and key annotations.

emitDecoratorMetadata

Required for runtime type reflection, used when resolving linked object types.

Resources

Useful links.