# Store data

Document collections with a small API, scoped automatically to the work that uses them.

Source: https://littleworks.app/docs/storage

## Start with a collection

Call `db.collection(name)` inside a work. A collection appears when its first record is written; there is no separate provisioning step. Feature and collection names start with a lowercase letter and contain lowercase letters, digits, underscores, or hyphens, up to 48 characters.

### Create a record inside a handler

```javascript
const notes = db.collection("notes");
const saved = await notes.create({ message: "Ready to go", status: "new" });
const sameNote = await notes.get(saved.id);
```

Each document is `{ id, data, revision, createdAt, updatedAt }`. A missing `get(id)` returns `null`. You can provide a stable ID with `create(data, { id })`; an existing ID produces a write conflict.

## Understand the data scope

Records are scoped by **store + feature + environment**. Two works with the same feature in the same store and environment share collections. A different feature or environment has separate data. Your code cannot select another store’s namespace.

## Read and filter

### List one page

```javascript
const page = await db.collection("notes").list({
  where: { status: "new" },
  limit: 25,
});

// Continue only when nextCursor is non-null.
if (page.nextCursor) {
  const nextPage = await db.collection("notes").list({
    where: { status: "new" },
    limit: 25,
    after: page.nextCursor,
  });
}
```

Lists return `{ items, nextCursor }`. The maximum page size is 100 documents. Filters support up to five top-level scalar equality comparisons. Pagination orders by document ID, not creation time. There are no joins, full-text search, arbitrary sorting, or SQL access.

## Update and delete with a revision

### Replace a document

```javascript
const notes = db.collection("notes");
const current = await notes.get(input.id);
if (!current) return Response.json({ error: "Not found" }, { status: 404 });

return notes.update(current.id, {
  ...current.data,
  status: "reviewed",
}, { revision: current.revision });
```

An update replaces the entire data object. Keep existing fields explicitly if you want to preserve them. Updates and deletes require the revision you read. A stale revision produces `WRITE_CONFLICT`; reload and reassess before retrying.

### Delete a document

```javascript
await notes.delete(current.id, { revision: current.revision });
```

## Write an atomic batch

### Two changes, one transaction

```javascript
await db.batch([
  { type: "create", collection: "notes", id: "note-001", data: { message: "Hello" } },
  { type: "create", collection: "receipts", id: "receipt-001", data: { noteId: "note-001" } },
]);
```

A batch supports up to 10 operations on distinct documents within the current scope. Every operation succeeds or the entire batch fails. A database batch does not include Shopify requests; it cannot roll back a Shopify mutation.

> **Record size**
> Each document body is limited to 16 KiB of serialized JSON. Store small structured records here. File and image storage are not provided.
