---
title: "Sequentially Chunked AttributeMap"
description: "Use this pattern for append-only data that must retain insertion order, such as agent messages, subscriber history, or audit events."
canonical_url: "https://docs.superdurable.io/design-patterns/sequentially-chunked-attribute-map/"
source: "docs/content/design-patterns/sequentially-chunked-attribute-map.mdx"
locale: "en"
language: "python"
---

> Index of every page for AI agents: https://docs.superdurable.io/llms.txt

# Sequentially Chunked AttributeMap

Code on this page is in Python. Other languages: [Go](https://docs.superdurable.io/design-patterns/sequentially-chunked-attribute-map.go.md) · [Java](https://docs.superdurable.io/design-patterns/sequentially-chunked-attribute-map.java.md) · [TypeScript](https://docs.superdurable.io/design-patterns/sequentially-chunked-attribute-map.typescript.md) · [Rust](https://docs.superdurable.io/design-patterns/sequentially-chunked-attribute-map.rust.md)

Use this pattern for append-only data that must retain insertion order, such as agent messages, subscriber history, or audit events.

If you keep this data in a single Attribute, the value keeps growing. Every append then reads and rewrites the whole value. A sequentially chunked **AttributeMap** splits the data into chunks, so an append rewrites only one chunk of bounded size. The sample stores at most 100 subscribers in one instance.

## Data layout

`ChunkedSubscriberFlow` is an RPC-only Flow. Start it once with no Flow timeout.

- `SubscriberArchiveState` stores the next sequence and the newest archived chunk token.
- `SubscriberChunks[current]` is the only mutable chunk.
- A full chunk moves to an immutable instance named by its zero-padded first sequence, such as **00000000000000000101**.

`RegisterSubscriber` locks the state and the **current** instance. Most calls rewrite only **current**. When **current** already holds 100 records, the same RPC call writes the archived chunk, starts a new **current** chunk, and advances the state. These writes take effect together.

Concurrent appends can receive a lock-conflict error. Retry after it; see [RPC lock conflicts](https://docs.superdurable.io/reference/server/runtime-data.md#rpc-lock-conflicts). To coordinate writes across the whole map, see [whole-map coordination](https://docs.superdurable.io/reference/server/runtime-data.md#whole-map-coordination).

`GetSubscriberPage` starts at **current** unless the caller supplies a page token. The HTTP controller uses **RPCInvokeOptions** to load only that instance. Each page returns its records newest first, plus the token of the next older page.

**Python**

```python
page = await app_state.client.invoke_rpc(
    flow.get_subscriber_page,
    FLOW_ID,
    GetSubscriberPageInput(page_token),
    options=RPCInvokeOptions(
        load_attribute_map_instances=(flow.subscriber_chunks.load(page_token),)
    ),
)
```

Example: [examples/python/dex_examples/patterns/sequentially-chunked-attribute-map/controller.py](https://github.com/superdurable/dex/tree/main/examples/python/dex_examples/patterns/sequentially-chunked-attribute-map/controller.py)

## Pagination rules

The **current** token is always valid after the Flow starts. An empty **current** returns an empty page. Archive tokens must contain exactly 20 decimal digits and identify a chunk boundary. A malformed token or a valid-looking token without a stored chunk returns an explicit error.

Archived chunks are immutable, so a page read again, such as on a retry, returns the same records. To update older records, use a different pattern or a separate index.

## HTTP API

```text
POST /patterns/sequentially-chunked-attribute-map/start
POST /patterns/sequentially-chunked-attribute-map/register
GET  /patterns/sequentially-chunked-attribute-map/subscribers?pageToken=current
```

The chunk size is part of the stored layout. A later version of the application can use a new chunk size for new archives. Its page-token logic must then read both layouts.

## Next

[Hash-Partitioned AttributeMap](https://docs.superdurable.io/design-patterns/hash-partitioned-attribute-map.md)
