- State & Storage
- Buckets
Buckets
Bucket Management
Section titled “Bucket Management”Buckets are namespaced containers for key-value pairs. Each bucket has its own configuration for expiration (TTL), size limits, and history.
Creating a Bucket
Section titled “Creating a Bucket”import { createClient } from "@ironflow/node";
const ironflow = createClient({ apiKey: "..." });const kv = ironflow.kv();
// Create a bucket with optional configurationconst info = await kv.createBucket({ name: "sessions", ttlSeconds: 3600, // Keys expire after 1 hour history: 5, // Keep last 5 revisions of each key});client := ironflow.NewClient(ironflow.ClientConfig{ APIKey: os.Getenv("IRONFLOW_API_KEY"),})
info, err := client.KV().CreateBucket(ctx, ironflow.BucketConfig{ Name: "sessions", TTL: time.Hour,})from ironflow import IronflowClient
client = IronflowClient(server_url="http://localhost:9123", api_key="ifkey_...")
info = client.kv_buckets(body={ "name": "sessions", "ttl_seconds": 3600, # Keys expire after 1 hour "history": 5, # Keep last 5 revisions of each key})The REST body uses snake_case (ttl_seconds, max_bytes), not the camelCase
the TypeScript SDK accepts.
Configuration Options
Section titled “Configuration Options”| Option | Type | Default | Description |
|---|---|---|---|
name | string | required | Unique bucket name. |
description | string | - | Optional human-readable description, returned on bucket info. |
ttlSeconds | number | 0 | Time-to-live for keys (0 = never expire). |
history | number | 1 | Number of historical revisions to keep per key. |
maxBytes | number | - | Maximum total size of the bucket in bytes. |
maxValueSize | number | - | Maximum size of a single value in bytes. |
Listing and Inspecting
Section titled “Listing and Inspecting”// List all bucketsconst buckets = await kv.listBuckets();
// Get metadata for a specific bucketconst stats = await kv.getBucketInfo("sessions");console.log(`Bucket has ${stats.values} values (keys including history) and is ${stats.bytes} bytes.`);// List all bucketsbuckets, err := client.KV().ListBuckets(ctx)
// Get infoinfo, err := client.KV().GetBucketInfo(ctx, "sessions")# List all bucketsbuckets = client.kv_list_buckets()print(buckets["count"], [b["name"] for b in buckets["buckets"]])
# Get metadata for a specific bucketstats = client.kv_get_buckets("sessions")print(f"Bucket has {stats['values']} values (keys including history) " f"and is {stats['bytes']} bytes.")
# Delete a bucket — removes all keys and history, cannot be undoneclient.kv_delete_buckets("old-cache")Deleting a Bucket
Section titled “Deleting a Bucket”await kv.deleteBucket("old-cache");client.kv_delete_buckets("old-cache")Environment Scope and Reserved Prefixes
Section titled “Environment Scope and Reserved Prefixes”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.
| Prefix | Owner | Visible in dashboard |
|---|---|---|
APP_ | User-created buckets | yes |
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.
Atomic Operations (CAS)
Section titled “Atomic Operations (CAS)”Key writes support optimistic concurrency control via HTTP headers:
| Header | Semantics |
|---|---|
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.
HTTP API Reference
Section titled “HTTP API Reference”| Method | Path | Description |
|---|---|---|
| POST | /api/v1/kv/buckets | Create a bucket. |
| GET | /api/v1/kv/buckets | List 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}/keys | List 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}/watch | WebSocket stream of KVWatchEvents. |