Clients
Connecting to a CapyDB K/V store over the Upstash REST protocol or RESP - @upstash/redis, @capydb/kv, ioredis, redis-py, go-redis and redis-cli.
A K/V store speaks two protocols. Both are standard, so migrating in is a URL and a token.
| Protocol | Endpoint | Use it from |
|---|---|---|
| Upstash REST over HTTPS | CAPYDB_KV_REST_URL | Serverless and edge runtimes, anything without a connection pool |
| RESP over TLS | rediss://…:6379 | Long-lived servers, blocking commands, pub/sub |
Upstash REST
The REST protocol carries pipelining, transactions and base64 encoding, so @upstash/redis works at
its default settings - including Upstash-Encoding: base64 and auto-pipelining, both of which the
client turns on for you.
import { Redis } from '@upstash/redis'
const redis = new Redis({
url: process.env.CAPYDB_KV_REST_URL!,
token: process.env.CAPYDB_KV_REST_TOKEN!,
})
await redis.set('user:1', { name: 'Ada' })
const user = await redis.get<{ name: string }>('user:1')
const [count, ttl] = await redis
.pipeline()
.incr('visits')
.ttl('visits')
.exec()Redis.fromEnv() reads UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN. CapyDB publishes
its own names, so either construct the client explicitly or set the UPSTASH_* names yourself.
Calling the endpoint directly, without a client:
curl "$CAPYDB_KV_REST_URL/set/greeting/hello" \
-H "Authorization: Bearer $CAPYDB_KV_REST_TOKEN"
curl "$CAPYDB_KV_REST_URL" \
-H "Authorization: Bearer $CAPYDB_KV_REST_TOKEN" \
-d '["GET", "greeting"]'@capydb/kv
@capydb/kv is a small factory that reads the CapyDB variable names and returns a configured
@upstash/redis client. It exists so you do not hand-wire the same three lines in every service; it
is not a wrapper, and the object it returns is an @upstash/redis client with nothing added.
npm install @capydb/kv @upstash/redisimport { createKv } from '@capydb/kv'
const kv = createKv()
await kv.set('hello', 'world')It reads CAPYDB_KV_REST_URL / CAPYDB_KV_REST_TOKEN, falling back to UPSTASH_REDIS_REST_URL /
UPSTASH_REDIS_REST_TOKEN so an existing Upstash deployment keeps working. It refuses a plaintext
http:// URL unless you opt in explicitly.
RESP
Ordinary Redis® OSS clients connect over TLS on port 6379, with the token as the password. Blocking commands and pub/sub work here and not over REST.
CapyDB publishes two environment variables, CAPYDB_KV_REST_URL and CAPYDB_KV_REST_TOKEN. It does
not publish a name for the RESP URL - the examples below read REDIS_URL, which is the ordinary
convention, and you set it yourself from the value the create or rotate response returned.
import Redis from 'ioredis'
const redis = new Redis(process.env.REDIS_URL!)
const job = await redis.blpop('queue', 0)import redis
r = redis.from_url(os.environ["REDIS_URL"])
r.set("hello", "world")opt, err := redis.ParseURL(os.Getenv("REDIS_URL"))
if err != nil {
return err
}
client := redis.NewClient(opt)redis-cli --tls -u "$REDIS_URL" PINGThe RESP URL embeds the token as its password, so it only exists in full on the create and rotate
responses. GET .../kv/credentials returns the endpoint without one and sets token_required: true; if you no longer have the token, rotate.
Commands that are not available
The store's ACL denies the administrative and replication surface. Everything a client application does is allowed; everything that would reconfigure the cell, take over its replication, or read another tenant's traffic is not:
CONFIG, SHUTDOWN, DEBUG, MODULE, REPLICAOF / SLAVEOF, SAVE / BGSAVE /
BGREWRITEAOF, ACL, CLUSTER, MIGRATE, SYNC / PSYNC, MONITOR, FAILOVER, RESET.
Persistence and eviction are managed by CapyDB, which is why CONFIG and the SAVE family are not
yours to call - see Operations.
Migrating from Upstash
Change two variables. The REST protocol, the client, the limiter and the command surface are the same; what changes is the region the store sits in and the fact that it is billed as part of your plan rather than per command.
If you already read UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN throughout your code,
set those names to CapyDB's values and change nothing else.