Documentation for agents: an index at /llms.txt, every docs page in one file at /llms-full.txt, and Markdown for any docs page by adding .md to its URL.

Effect KitRedis

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

ConstructorUse
RedisUpstash.layerSettings as an object. Includes Effect's FetchHttpClient.
RedisUpstash.layerConfigSettings from an Effect Config.
RedisUpstash.layerWithHttpClientSettings 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 >;
type Provided = BatchExecutor | CommandExecutor | Redis | RedisCredentials | UpstashEvents

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, WATCH and blocking commands.
  • Client-side caching and tracking.
  • Cluster and Sentinel routing. CLUSTER, SENTINEL, CLIENT and commands with an explicit node or slot target fail with UpstashError where reason is "unsupported" and delivery is "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.