Skip to content
Ironflow is pre-1.0: APIs can change between releases. Pin a version. What is ready →

Buckets

Buckets are namespaced containers for key-value pairs. Each bucket has its own configuration for expiration (TTL), size limits, and history.

import { createClient } from "@ironflow/node";
const ironflow = createClient({ apiKey: "..." });
const kv = ironflow.kv();
// Create a bucket with optional configuration
const info = await kv.createBucket({
name: "sessions",
ttlSeconds: 3600, // Keys expire after 1 hour
history: 5, // Keep last 5 revisions of each key
});

OptionTypeDefaultDescription
namestringrequiredUnique bucket name.
descriptionstring-Optional human-readable description, returned on bucket info.
ttlSecondsnumber0Time-to-live for keys (0 = never expire).
historynumber1Number of historical revisions to keep per key.
maxBytesnumber-Maximum total size of the bucket in bytes.
maxValueSizenumber-Maximum size of a single value in bytes.

// List all buckets
const buckets = await kv.listBuckets();
// Get metadata for a specific bucket
const stats = await kv.getBucketInfo("sessions");
console.log(`Bucket has ${stats.values} values (keys including history) and is ${stats.bytes} bytes.`);

await kv.deleteBucket("old-cache");
client.kv_delete_buckets("old-cache")

A bucket belongs to the environment of the key that creates it. Two environments can each have a bucket named sessions, and they do not share data. A request that has no environment scope gets 403 request has no environment scope.

Internally, the env_default environment stores a bucket as APP_<name> (for example APP_sessions). Every other environment stores it as APP_ENV_<hash>_<name>, where <hash> is 32 hex characters of the SHA-256 of the environment ID. Internal Ironflow buckets use a SYS_ prefix. They are hidden from the KV Store dashboard and from listBuckets(). You never type these prefixes — the SDK and API always accept and return the plain name.

PrefixOwnerVisible in dashboard
APP_User-created bucketsyes
SYS_Ironflow internals (config, secrets, cron triggers, debounce state, policy epoch, …)no

A bucket name that starts with SYS_, ENV_, config_env_ or MOD_ is reserved. Create returns 400, and get, list-keys and the key operations return 404 bucket not found. Delete of a SYS_ name returns 403. All reserved names are listed in Reserved names.

If you inspect NATS directly (e.g. nats kv ls), you will see the prefixed names.


Key writes support optimistic concurrency control via HTTP headers:

HeaderSemantics
If-None-Match: *Create only if the key does not exist. Returns 412 on conflict.
If-Match: <revision>Update only if the current revision matches. Returns 412 on mismatch.
(none)Unconditional put — overwrites any existing value.

The SDK exposes these as bucket.create(key, value) and bucket.update(key, value, revision). See Key Operations for examples.


MethodPathDescription
POST/api/v1/kv/bucketsCreate a bucket.
GET/api/v1/kv/bucketsList buckets.
GET/api/v1/kv/buckets/{bucket}Get bucket info.
DELETE/api/v1/kv/buckets/{bucket}Delete a bucket.
GET/api/v1/kv/buckets/{bucket}/keysList keys (supports ?filter=).
GET/api/v1/kv/buckets/{bucket}/keys/{key}Get a value (returns ETag: <revision>).
PUT/api/v1/kv/buckets/{bucket}/keys/{key}Put / create / update (supports If-Match / If-None-Match).
DELETE/api/v1/kv/buckets/{bucket}/keys/{key}Tombstone the key (?purge=true for hard delete).
GET/api/v1/kv/buckets/{bucket}/watchWebSocket stream of KVWatchEvents.