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.
apprail caches create shop sessions
apprail caches create shop jobs --memory 512 --eviction noeviction --persist --storage 5| Option | Choices |
|---|---|
--memory | 64 MB–4 GB. Data may use 75% of it; the rest is headroom |
--eviction | allkeys-lru (default), allkeys-lfu, volatile-lru, or noeviction (writes fail when full) |
--persist | Keep 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.
apprail queues create shop orders
apprail queues create shop emails --max-deliveries 3 --memory 512 --storage 5Your 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
| Promise | Detail |
|---|---|
| At least once | A message is delivered again until a consumer acknowledges it, so handlers must tolerate seeing a message twice |
| Bounded retries | After --max-deliveries redeliveries (1–20, default 5) a message moves to <name>.dead and stays there until you take it |
| Order | First in, first out only with one consumer and no redeliveries |
| Durability | Messages 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
apprail caches rotate-password shop sessions
apprail queues rotate-password shop ordersA 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.