# DynamoDB DocumentClient Usage with Native JavaScript Types: Complete Guide

> Master DynamoDB DocumentClient with native JavaScript types. This guide simplifies data conversion, offering TypeScript safety and flexible number handling for your AWS applications.

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

---

**The DynamoDB DocumentClient (`@aws-sdk/lib-dynamodb`) automatically marshals native JavaScript primitives, arrays, and objects into DynamoDB's AttributeValue format, eliminating manual type conversion while providing TypeScript-safe inference and configurable number handling.**

Working with Amazon DynamoDB in modern JavaScript applications typically requires translating between native language types and the service's low-level wire format. According to the `aws/agent-toolkit-for-aws` repository, the DynamoDB DocumentClient provides a high-level abstraction that handles this conversion transparently, allowing developers to work with plain JavaScript objects while the SDK manages the underlying `{ S: "...", N: "123" }` structures internally.

## Architecture and Type Conversion

The DocumentClient operates as a thin wrapper around the base `DynamoDBClient` from `@aws-sdk/client-dynamodb`. When you send commands through the DocumentClient, the library intercepts inputs and outputs to perform automatic serialization.

**Marshalling** occurs before requests leave your application. The client inspects JavaScript values and converts them according to a static mapping table: strings become `S` types, numbers become `N` types, booleans become `BOOL`, arrays become `L` (lists), and objects become `M` (maps). This transformation happens 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) lines 32-43, which defines the type correspondence logic used by the SDK.

**Unmarshalling** reverses the process on responses. By default, DynamoDB numbers convert to JavaScript `number` primitives. However, for arbitrary-precision arithmetic, you can enable the `wrapNumbers` option to receive `NumberValue` objects instead, as documented in the reference file lines 55-57.

## Configuration Options for Marshalling Behavior

You can customize how the DocumentClient handles edge cases through `marshallOptions` and `unmarshallOptions` passed to the factory method.

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

const client = DynamoDBDocumentClient.from(new DynamoDBClient({}), {
  marshallOptions: {
    removeUndefinedValues: true,  // Strip undefined fields from items
    convertEmptyValues: false,    // Preserve empty strings rather than converting to null
  },
  unmarshallOptions: {
    wrapNumbers: true,            // Return NumberValue for all numeric data
  },
});

```

These configuration parameters are detailed 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) lines 47-55. The `removeUndefinedValues` option is particularly useful when working with sparse schemas, preventing the SDK from sending empty AttributeValue objects to the service.

## Handling Large Numbers and Binary Data

JavaScript's `number` type cannot safely represent integers larger than `2^53 - 1`. When working with DynamoDB attributes that exceed `Number.MAX_SAFE_INTEGER`, use the `NumberValue` class to maintain precision.

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

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

await client.send(
  new PutCommand({
    TableName: "FinancialRecords",
    Item: {
      accountId: "ACC-123",
      balance: NumberValue.from("1000000000000000000000.000000001"),
    },
  })
);

```

This pattern, documented in lines 60-70 of the DynamoDB reference file, ensures that monetary values and other high-precision data remain intact without floating-point corruption. The DocumentClient also natively supports JavaScript `Set` objects and binary data (`Buffer` or `Uint8Array`), converting them to DynamoDB's `SS`, `NS`, `BS`, and `B` types automatically.

## CRUD Operations with Native Types

The following example demonstrates basic create, read, update, and delete operations using plain JavaScript objects. Notice the absence of AttributeValue notation—the DocumentClient handles the marshalling internally.

```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 types marshaled automatically
await client.send(
  new PutCommand({
    TableName: "Users",
    Item: { 
      id: "user-456", 
      name: "Alice", 
      age: 30, 
      active: true,
      tags: new Set(["admin", "beta"])
    },
  })
);

// Read
const { Item } = await client.send(
  new GetCommand({ TableName: "Users", Key: { id: "user-456" } })
);
console.log(Item); // { id: 'user-456', name: 'Alice', age: 30, active: true, tags: Set { ... } }

// Query with expression attributes
const { Items } = await client.send(
  new QueryCommand({
    TableName: "Users",
    KeyConditionExpression: "id = :id",
    ExpressionAttributeValues: { ":id": "user-456" },
  })
);

// Delete
await client.send(
  new DeleteCommand({ TableName: "Users", Key: { id: "user-456" } })
);

```

This implementation mirrors the 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) lines 7-28, which serve as the authoritative reference for the Agent Toolkit.

## Pagination with Native Type Unmarshalling

The DocumentClient integrates seamlessly with the SDK's paginator utilities, automatically unmarshalling each page of results into native JavaScript arrays.

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

const paginator = paginateScan(
  { client }, 
  { TableName: "Users", Limit: 100 }
);

for await (const page of paginator) {
  console.log(page.Items); // Already converted from AttributeValue format
}

```

As shown in lines 82-89 of the reference documentation, the `paginateScan` function returns an async iterator where each page contains native JavaScript objects rather than raw DynamoDB attribute maps.

## Summary

- **DynamoDB DocumentClient** wraps the low-level `DynamoDBClient` to provide automatic marshalling between native JavaScript types and DynamoDB AttributeValue formats.
- **Configuration options** (`marshallOptions` and `unmarshallOptions`) let you control undefined value handling, empty string conversion, and number wrapping behavior.
- **Large number support** via the `NumberValue` class prevents precision loss when working with values exceeding JavaScript's safe integer limits.
- **Pagination utilities** like `paginateScan` work transparently with the DocumentClient, returning unmarshalled JavaScript objects in each iteration.
- **Source files** in `aws/agent-toolkit-for-aws` (specifically [`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) and [`SKILL.md`](https://github.com/aws/agent-toolkit-for-aws/blob/main/SKILL.md)) provide the authoritative implementation details for these patterns.

## Frequently Asked Questions

### How does DynamoDB DocumentClient handle JavaScript undefined values?

By default, the DocumentClient throws an error when encountering `undefined` values in item attributes. However, you can configure `marshallOptions.removeUndefinedValues: true` during client creation to silently strip these fields before sending them to DynamoDB. This behavior is defined in the marshalling options section of the Agent Toolkit reference documentation.

### Can I use DynamoDB DocumentClient with TypeScript generics for type safety?

Yes. The DocumentClient ships with TypeScript definitions that allow you to specify the shape of your items using generics on command constructors. For example, `new GetCommand<{ id: string; count: number }>(...)` provides compile-time checking for attribute names and types, while the SDK still handles the runtime marshalling to AttributeValue format.

### What is the performance difference between DocumentClient and the low-level DynamoDB client?

The DocumentClient adds a small serialization overhead for converting between native types and AttributeValue structures. For performance-critical workloads requiring microsecond-level optimization, you can bypass this layer by using the raw `DynamoDBClient` from `@aws-sdk/client-dynamodb` and constructing AttributeValue objects manually. However, for most applications, the convenience and reduced error rate of automatic marshalling outweigh the minimal overhead.

### How do I store binary data using DynamoDB DocumentClient?

Pass `Buffer`, `Uint8Array`, or `Blob` objects directly in your item attributes. The DocumentClient automatically converts these to DynamoDB's `B` (binary) type during marshalling. When reading back, the values are returned as `Uint8Array` instances by default, preserving the original binary data without manual Base64 encoding or decoding.