Upstash
Use Redis over HTTPS from Deno, Cloudflare Workers, Bun or Node.js with RedisUpstash.
RedisUpstash talks to Upstash over HTTPS using Effect's HTTP client, so it runs where raw sockets are not available, including Deno and Cloudflare Workers. It also runs on Node.js and Bun. Import it from @effect-kit/redis/upstash.
Example (Creating the Upstash Layer)
import { , } from "effect";
import { } from "@effect-kit/redis";
import { } from "@effect-kit/redis/upstash";
const = .(
.({
: .("UPSTASH_REDIS_REST_URL"),
: .("UPSTASH_REDIS_REST_TOKEN"),
}),
);
const = .(function* () {
const = yield* ;
return yield* .("greeting");
});
export const = .(.());Creating the layer
| Constructor | Use |
|---|---|
RedisUpstash.layer | Settings as an object. Includes Effect's FetchHttpClient. |
RedisUpstash.layerConfig | Settings from an Effect Config. |
RedisUpstash.layerWithHttpClient | Settings as an object. You provide the HttpClient. |
The url must be https:, with no credentials, query string, hash or path. Authenticate with token (a Redacted string) or with credentials (see Credentials), not both. A plain-string token is a type error.
Prop
Type
Provided services
The layer provides Redis, BatchExecutor, CommandExecutor, RedisCredentials and UpstashEvents.
Example (The Services an Upstash Layer Provides)
import type { } from "effect";
import { } from "effect";
import { } from "@effect-kit/redis/upstash";
const = .({
: "https://example.upstash.io",
: .("token"),
});
type Provided = .<typeof >;No sessions over HTTP
RedisSessions, RedisPubSub, RedisStreams, RedisScripts and RedisAdmin are not provided.
A program that requires one does not type-check against this layer.
What works over HTTP
Ordinary commands, pipelines and transactions work. A pipeline or transaction is one request. Pub/Sub is text only, through UpstashEvents.subscribe; see Pub/Sub.
These do not exist over HTTP:
- Sessions,
WATCHand blocking commands. - Client-side caching and tracking.
- Cluster and Sentinel routing.
CLUSTER,SENTINEL,CLIENTand commands with an explicit node or slot target fail withUpstashErrorwherereasonis"unsupported"anddeliveryis"unsent".
Binary request positions are limited. Invalid UTF-8 in an argument fails with UpstashError and reason: "encoding". A transaction rejects commands whose replies are ambiguous, which means raw commands, custom commands and scripts.
redis.upstash holds Upstash's own commands, such as searchCreate, searchQuery, vectorCreate, vectorQuery and aclRestToken.
Handling UpstashError
UpstashError has a stage (config, request, response or stream), a reason, and a delivery. Over HTTP, delivery is unsent, unknown or replied. It is unknown, never possibly-written: a request that failed in flight may have run.
A 429 response has reason: "rate-limit". When the response had a Retry-After header, retryAfterSeconds holds it. A 401 or 403 is reason: "authentication". The package does not retry either. Because the status errors have delivery: "unknown", wait and retry only commands that are safe to run twice.
Example (Reading the Retry Hint From a Rate Limit)
import { } from "effect";
import { } from "@effect-kit/redis";
export const = .(function* () {
const = yield* ;
return yield* .("greeting");
}).(
.("UpstashError", () =>
. === "rate-limit"
? .(`rate limited, retry after ${. ?? "?"} seconds`)
: .(),
),
);Tested version
Upstash is tested against hosted instances in isolated tests, over both HTTP and native RESP. To use Upstash over a native socket instead, connect with RedisNode.layer and a rediss:// URL.