Skip to content

Tables

Store items in tables with partition keys, optional sort keys, and index tables.

Declare a table

Add an entry under resources.tables[] in stack.json, then run kernstack deploy. See the IAC reference.

Seed data

Place seed items at seed/tables/{name}.json or seed/tables/{name}.jsonl and omit seed from the table entry. The CLI batch-puts after each successful deploy. Set seed explicitly when the file lives elsewhere.

Each attribute must be a typed value (S, N, B, BIN, L, M, NULL), not a plain JSON string or number:

[
  {
    "id": { "S": "user-1" },
    "email": { "S": "ada@example.com" },
    "visits": { "N": "3" }
  }
]

Item expiry (TTL)

Set the reserved attribute -ttl to a Unix epoch time in seconds (type N). Items whose -ttl has passed are deleted by a background sweep on the owning partition; the deletion is replicated and propagated to every secondary index like a normal DeleteItem.

{
  "conID": { "S": "conn-1" },
  "uID": { "S": "user-1" },
  "-ttl": { "N": "1790607696" }
}

Only the exact name -ttl is honoured. An attribute called ttl, expiresAt, or similar is stored as ordinary data and never triggers expiry.

Change streams

Set change_stream.function on a table to invoke a function of the same stack whenever items are written or deleted. See the IAC reference.

{ "name": "orders", "key_name": "id", "key_type": "S", "indexes": [], "change_stream": { "function": "on-order" } }
  • Every change made while the stream is enabled is delivered at least once, in batches of up to 100 records. Changes to the same item arrive in the order they were written.
  • A failed batch (the function cannot be reached, returns a 5xx or 429 status, or the handler returns an error) is retried with backoff, and later changes wait until it succeeds. Changes still undelivered after 24 hours are skipped. Other 4xx responses are not retried.
  • A record can occasionally be delivered more than once. Make handlers idempotent; change_id identifies a change.
  • Re-enabling a disabled stream starts from that moment. Pointing it at a different function continues where it left off.

Each invocation has trigger_type change_stream, change_table (the table name) and change_records:

Field Meaning
change_type INSERT (put, or an update that created the item), MODIFY (update of an existing item) or REMOVE (delete)
keys Partition key and sort key of the item, as typed values
old_item Item before the change; absent when the item did not exist
new_item Item after the change; absent for REMOVE
change_id Opaque string unique to the change; a redelivered record has the same value
{
  "trigger_type": "change_stream",
  "change_table": "orders",
  "change_records": [
    {
      "change_type": "MODIFY",
      "keys": { "id": { "S": "order-1" } },
      "old_item": { "id": { "S": "order-1" }, "status": { "S": "new" } },
      "new_item": { "id": { "S": "order-1" }, "status": { "S": "paid" } },
      "change_id": "3f9a1c0e7b2d4a5f8c6e1b0d9a7f2e4c"
    }
  ]
}

For a Go handler, see functions.

CLI

Operation Command
List tables kernstack inspect tables
Put item kernstack inspect tables put TABLE --item item.json
Batch put kernstack inspect tables put TABLE --items items.json
Get item kernstack inspect tables get TABLE -k JSON [--sort-key JSON]
Delete item kernstack inspect tables delete TABLE -k JSON [--sort-key JSON]
Query kernstack inspect tables query TABLE --key-name NAME -k JSON
Scan kernstack inspect tables scan TABLE
kernstack inspect tables put users --item ./user.json
kernstack inspect tables get users -k '{"S":"user-1"}'
kernstack inspect tables query users --key-name id -k '{"S":"user-1"}'