effect-mq/redis) keeps every operation atomic with a single Lua script, so you can use Upstash Redis as its storage.
Install
effect-mq targets Effect v4, which is currently published under the rc tag; @effect/platform-node@latest still targets Effect v3, so install it with the rc tag as well. The Redis store does not bundle a client; on Node.js it uses node-redis through @effect/platform-node. On Bun, install @effect/platform-bun@rc instead and use BunRedis (no extra client needed).
Usage
First, get your connection string from the TCP tab of the Connect section on your database page in the Upstash Console:
rediss:// since Upstash requires TLS; node-redis picks up TLS from the scheme automatically, so no extra options are needed:
RunnerLive to your app and the worker claims, runs, retries, and records jobs. The producer only needs StoreLive, so your API server can enqueue without depending on any handler code.
Connecting over HTTP
The setup above talks to Upstash over a TCP connection, which suits a long-running worker process. You may prefer to connect over HTTP with@upstash/redis instead when:
- You enqueue jobs from serverless or edge functions. Vercel Functions, Cloudflare Workers, Lambda, and similar runtimes either have no TCP sockets or would open a fresh TLS connection on every cold start.
@upstash/redisusesfetch, so it works anywhere and has no connection to manage. - You run many short-lived instances. Each TCP client holds a connection open (two for the worker, one of them for pub/sub), which adds up across many serverless invocations or autoscaled replicas. HTTP requests are stateless, so there is no connection count to watch.
Redis service, which only requires a send function for raw commands and a subscribe function for pub/sub wake-ups. @upstash/redis provides both (exec and subscribe), so the same store, Lua scripts, and key layout work unchanged.
Install the client:
Redis service over the Upstash REST API:
upstash-redis.ts
NodeRedis, using the REST URL and token from the REST tab of the Connect section on your database page:
enqueue, execute, and workers all work over HTTP, including pub/sub wake-ups so idle workers pick up new jobs immediately instead of waiting for pollInterval.
Because both clients run the same Lua scripts against the same keys, you can mix them under one prefix. A common split is to enqueue over HTTP from serverless functions and run the worker over TCP on a long-running process.
Billing Optimization
effect-mq workers poll Redis regularly (pollInterval), heartbeat locks on active jobs, and sweep for stalled jobs and history, even when there is no queue activity. This can incur extra costs because Upstash charges per request on the Pay-As-You-Go plan. With the introduction of our Fixed plans, we recommend switching to a Fixed plan to avoid increased command count and high costs in effect-mq use cases.