Data

Caches & queues

A Redis-compatible cache for sessions, rate limits, and hot data, and a RabbitMQ queue with retries and dead-lettering built in — both in your environment’s private network.

Caches (Valkey)

A cache is a Valkey 8 server: open source and compatible with Redis clients and commands.

Terminal
apprail caches create shop sessions
apprail caches create shop jobs --memory 512 --eviction noeviction --persist --storage 5
OptionChoices
--memory64 MB–4 GB. Data may use 75% of it; the rest is headroom
--evictionallkeys-lru (default), allkeys-lfu, volatile-lru, or noeviction (writes fail when full)
--persistKeep data on disk (append-only file, flushed about every second), with --storage 1–20 GB

Your app reads REDIS_URL (redis://default:…@…:6379), plus APPRAIL_CACHE_<NAME>_URL, _HOST, _PORT, and _PASSWORD. Any Redis client works.

A cache is a cache. Without --persist, its contents live only in memory and disappear on any restart — a reboot, a move, an upgrade, or a password rotation. With it, data survives restarts but a crash can lose the last second, and there’s no offsite copy. Keep anything you can’t lose in Postgres.

Queues (RabbitMQ)

A queue is a RabbitMQ 4 server that starts with a durable queue named after it, plus <name>.dead for messages that keep failing.

Terminal
apprail queues create shop orders
apprail queues create shop emails --max-deliveries 3 --memory 512 --storage 5

Your app reads AMQP_URL (also as RABBITMQ_URL) and APPRAIL_QUEUE_<NAME>_URL, _QUEUE, _DEAD_LETTER_QUEUE, _MAX_DELIVERIES, and the host, port, user, and password separately.

// Node.js (amqplib): publish persistently, acknowledge after the work is done
const conn = await amqp.connect(process.env.AMQP_URL);
const ch = await conn.createChannel();
ch.sendToQueue(process.env.APPRAIL_QUEUE_ORDERS_QUEUE, Buffer.from(JSON.stringify(order)), { persistent: true });

await ch.consume("orders", async (msg) => {
  await handle(JSON.parse(msg.content.toString()));  // make this safe to run twice
  ch.ack(msg);
});

What delivery means

PromiseDetail
At least onceA message is delivered again until a consumer acknowledges it, so handlers must tolerate seeing a message twice
Bounded retriesAfter --max-deliveries redeliveries (1–20, default 5) a message moves to <name>.dead and stays there until you take it
OrderFirst in, first out only with one consumer and no redeliveries
DurabilityMessages published as persistent survive restarts. There’s one server on one disk and no offsite copy

Workers that consume a queue can scale on its backlog. The queue refuses new messages rather than filling its disk. Queue depths — ready, in progress, and dead-lettered — are shown in the console. You can declare more queues on the same server from your app.

Rotating credentials

Terminal
apprail caches rotate-password shop sessions
apprail queues rotate-password shop orders

A queue’s password changes without a restart: open connections and every message survive, and services are updated with the new password. A cache restarts with its new password (losing in-memory contents), then services reconnect about 30 seconds later.

Deleting

apprail caches delete shop sessions --confirm sessions and apprail queues delete shop orders --confirm orders remove the server, its disk, and its credentials — including any dead-lettered messages.