# How to Use DynamoDB DocumentClient with Native JavaScript Types

> Learn to use DynamoDB DocumentClient with native JavaScript types. Effortlessly convert data without manual attribute value construction. Enhance your AWS development.

- Repository: [Amazon Web Services/agent-toolkit-for-aws](https://github.com/aws/agent-toolkit-for-aws)
- Tags: how-to-guide
- Published: 2026-07-03

---

**The DynamoDB DocumentClient automatically converts native JavaScript types to DynamoDB's AttributeValue format and unmarshals query results back to plain objects, eliminating the need to manually construct `{ S: "...", N: "123" }` structures.**

Working with Amazon DynamoDB in the AWS SDK for JavaScript v3 becomes significantly more intuitive when you use the DynamoDB DocumentClient with native JavaScript types. This high-level abstraction, available in the `@aws-sdk/lib-dynamodb` package, bridges the gap between DynamoDB's underlying type system and idiomatic JavaScript code. According to the aws/agent-toolkit-for-aws repository, this approach is the recommended way to handle automatic marshalling while maintaining full type safety and supporting advanced features like pagination and large number handling.

## What Is DynamoDB DocumentClient?

The **DynamoDB DocumentClient** is a high-level helper that wraps the low-level `DynamoDBClient` from `@aws-sdk/client-dynamodb`. While the underlying client handles HTTP transport, request signing, retries, and pagination, the DocumentClient adds a transformation layer that intercepts command inputs and outputs.

This architecture allows you to work with plain JavaScript objects, arrays, and primitives rather than the verbose `AttributeValue` structures required by the base client. The DocumentClient is type-safe and ships with full TypeScript definitions, enabling your editor to infer the shape of `Item` objects and command inputs.

## How Automatic Marshalling Works

The DocumentClient processes data through two distinct phases as documented in [`skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md):

1. **Marshalling** – When sending commands, the client converts JavaScript primitives, arrays, objects, and `Set`s into appropriate DynamoDB types (`S`, `N`, `BOOL`, `L`, `M`, etc.) based on a static mapping table【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L32-L43】.

2. **Unmarshalling** – Responses are transformed back into native JavaScript values. By default, numbers become JavaScript `number` primitives, though you can enable `wrapNumbers` to receive `NumberValue` objects for arbitrary-precision arithmetic【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L55-L57】.

## Configuration Options for Marshalling

You can customize the transformation behavior via `marshallOptions` and `unmarshallOptions` when instantiating the client:

```javascript
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

const client = DynamoDBDocumentClient.from(new DynamoDBClient({}), {
  marshallOptions: {
    removeUndefinedValues: true,  // Drop undefined fields automatically
    convertEmptyValues: false,  // Preserve empty strings as-is
  },
  unmarshallOptions: {
    wrapNumbers: true,          // Return NumberValue instead of number
  },
});

```

These options are documented in the "Marshall Options" section of the DynamoDB reference file【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L47-L55】.

## Working with Large Numbers and Binary Data

By default, DynamoDB numbers are unmarshalled to JavaScript numbers. For values exceeding `Number.MAX_SAFE_INTEGER`, use the `NumberValue` class:

```javascript
import { NumberValue, DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";

const client = DynamoDBDocumentClient.from(new DynamoDBClient({}));

await client.send(
  new PutCommand({
    TableName: "MyTable",
    Item: {
      id: "1",
      bigNum: NumberValue.from("1000000000000000000000.000000001"),
    },
  })
);

```

This approach ensures precision for financial or scientific data without losing fractional components. The DocumentClient also handles `Set` and binary data types automatically, converting them to native JavaScript `Set` objects and `Uint8Array` buffers respectively【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L60-L70】.

## Paginating Results with DocumentClient

The DocumentClient integrates with the SDK's paginator utilities to handle `LastEvaluatedKey` automatically:

```javascript
import { paginateScan } from "@aws-sdk/lib-dynamodb";

for await (const page of paginateScan({ client }, { TableName: "MyTable", Limit: 100 })) {
  console.log(page.Items);
}

```

This pattern eliminates manual pagination logic while working with native JavaScript types throughout the iteration【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L82-L89】.

## Complete CRUD Implementation Examples

The following example demonstrates creating, reading, querying, and deleting items using native JavaScript types:

```javascript
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  PutCommand,
  GetCommand,
  QueryCommand,
  DeleteCommand,
} from "@aws-sdk/lib-dynamodb";

const client = DynamoDBDocumentClient.from(
  new DynamoDBClient({ region: "us-east-1" })
);

// Create - native JS types are marshaled automatically
await client.send(
  new PutCommand({
    TableName: "MyTable",
    Item: { id: "1", name: "Alice", age: 30, active: true },
  })
);

// Read
const { Item } = await client.send(
  new GetCommand({ TableName: "MyTable", Key: { id: "1" } })
);
console.log(Item); // { id: '1', name: 'Alice', age: 30, active: true }

// Query with simple expressions
const { Items } = await client.send(
  new QueryCommand({
    TableName: "MyTable",
    KeyConditionExpression: "id = :id",
    ExpressionAttributeValues: { ":id": "1" },
  })
);

// Delete
await client.send(
  new DeleteCommand({ TableName: "MyTable", Key: { id: "1" } })
);

```

This implementation mirrors the canonical examples found in [`skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md)【/cache/repos/github.com/aws/agent-toolkit-for-aws/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md#L7-L28】.

## Summary

- **DynamoDBDocumentClient** from `@aws-sdk/lib-dynamodb` eliminates the need to manually construct AttributeValue structures when working with DynamoDB.
- **Automatic marshalling** handles JavaScript objects, arrays, Sets, and binary data, with configurable options for undefined values and empty strings.
- **Large number support** requires enabling `wrapNumbers` and using the `NumberValue` class for values exceeding JavaScript's safe integer range.
- **Native pagination** is available through `paginateScan` and `paginateQuery` functions that maintain type safety throughout result sets.

## Frequently Asked Questions

### What is the difference between DynamoDBClient and DynamoDBDocumentClient?

`DynamoDBClient` is the low-level client requiring manual `{ S: "value" }` AttributeValue structures, while `DynamoDBDocumentClient` wraps it to automatically marshal native JavaScript types. The DocumentClient uses the same underlying HTTP transport and signing mechanisms but intercepts commands to transform inputs and outputs according to the mapping defined in [`skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md).

### How do I handle undefined values in JavaScript objects?

Configure `marshallOptions.removeUndefinedValues: true` when creating the DocumentClient. As documented in the aws/agent-toolkit-for-aws reference files, this option strips undefined fields from objects before sending them to DynamoDB, preventing validation errors that occur when undefined values are present in the Item.

### Can DynamoDB DocumentClient handle numbers larger than Number.MAX_SAFE_INTEGER?

Yes. Enable `unmarshallOptions.wrapNumbers: true` to receive `NumberValue` objects instead of primitive numbers. For writes, explicitly construct `NumberValue.from("...")` with the string representation of your large number, as shown in the large-number handling section of [`skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/skills/core-skills/aws-sdk-js-v3-usage/references/dynamodb.md).

### How do I paginate results without writing manual loops?

Use the `paginateScan` or `paginateQuery` functions exported by `@aws-sdk/lib-dynamodb`. These async generators yield pages of results and automatically handle the `LastEvaluatedKey`/`ExclusiveStartKey` pattern, allowing you to iterate with `for await...of` as demonstrated in the pagination examples within the repository.