Valkey
Tested with: Valkey 8.1.3 on Databasezy · zb CLI 0.1
Valkey is the open-source (BSD-3-Clause) continuation of Redis, maintained under the Linux Foundation. It is the key-value engine on Databasezy for caches, queues, sessions, rate limits and pub/sub.
Overview
Section titled “Overview”Valkey speaks RESP, the Redis protocol, so Redis client libraries work unchanged. Each instance is a single node with persistence turned on (RDB snapshots plus the append-only file).
| Status | Available |
|---|---|
| Category | Key-value |
| Versions | 9.1, 8.1, 8.0 (newest is the default) |
| Protocol and port | RESP (Redis protocol) on 6379 |
| Runtime | Single-node engine (valkey/valkey) |
| Backups | RDB + AOF |
| Point-in-time recovery | No |
| Pause | Scale to zero |
| Free plan | Yes (size f0) |
| Licence | BSD-3-Clause |
Create an instance
Section titled “Create an instance”- Open the portal and choose New instance.
- Pick Valkey and a version (9.1, 8.1, 8.0).
- Choose a size and region. On the Free plan the size is f0. Secure placement is listed only after your organization has signed the BAA.
- Check the hourly price and monthly estimate, then confirm. The Connect tab fills in when the instance is ready.
zb instances create --engine valkey --engine-version 9.1 \ --size s1 --region us-east --name valkey-demo --wait# On the Free plan, use --size f0
# Reveal the credentials once and store them in your secret managerzb instances credentials reveal valkey-democurl -sS https://api.databasezy.com/v1/orgs/$ZB_ORG/projects/$ZB_PROJECT/instances \ -H "Authorization: Bearer $ZB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "engine": "valkey", "engine_version": "9.1", "size": "s1", "region": "us-east", "name": "valkey-demo"}'
The response is 201 with the instance in status requested, or 202 when a
team approval policy applies. See the REST API reference.
Connect
Section titled “Connect”The RESP endpoint accepts TLS only, and you connect with the generated password of the default user. Use
rediss:// URLs and keep hostname checking on; clients that ask for a username use default.
Valkey listens on port 6379 (RESP (Redis protocol)). Versions: 9.1, 8.1, 8.0. Replace the example host with the one on your instance's Connect tab; credentials are shown once at creation.
rediss://default:<password>@valkey-7f3k.us-east.databasezy.com:6379/0import { readFileSync } from "node:fs";import Redis from "ioredis";
const host = "valkey-7f3k.us-east.databasezy.com";export const redis = new Redis({ host, port: 6379, username: "app", password: process.env.ZB_PASSWORD, tls: { ca: readFileSync("databasezy-ca.pem", "utf8"), servername: host, // hostname verification rejectUnauthorized: true, }, maxRetriesPerRequest: 3,});
await redis.set("hello", "world", "EX", 60);console.log(await redis.get("hello"));Tested with: Valkey 9.1 · ioredis 5.4
import osimport valkey # or: import redis as valkey
r = valkey.Valkey( host="valkey-7f3k.us-east.databasezy.com", port=6379, username="app", password=os.environ["ZB_PASSWORD"], ssl=True, ssl_cert_reqs="required", ssl_ca_certs="databasezy-ca.pem", ssl_check_hostname=True, decode_responses=True,)r.set("hello", "world", ex=60)print(r.get("hello"))Tested with: Valkey 9.1 · valkey-py 6.0 (redis-py 5.x compatible)
package main
import ( "context" "crypto/tls" "crypto/x509" "fmt" "os"
"github.com/valkey-io/valkey-go")
func main() { pem, _ := os.ReadFile("databasezy-ca.pem") roots := x509.NewCertPool() roots.AppendCertsFromPEM(pem)
client, err := valkey.NewClient(valkey.ClientOption{ InitAddress: []string{"valkey-7f3k.us-east.databasezy.com:6379"}, Username: "app", Password: os.Getenv("ZB_PASSWORD"), TLSConfig: &tls.Config{RootCAs: roots, ServerName: "valkey-7f3k.us-east.databasezy.com", MinVersion: tls.VersionTLS12}, }) if err != nil { panic(err) } defer client.Close()
ctx := context.Background() client.Do(ctx, client.B().Set().Key("hello").Value("world").Ex(60*1e9).Build()) v, _ := client.Do(ctx, client.B().Get().Key("hello").Build()).ToString() fmt.Println(v)}Tested with: Valkey 9.1 · valkey-go 1.0 (go-redis v9 works the same)
use redis::{AsyncCommands, Client, TlsCertificates};
#[tokio::main]async fn main() -> redis::RedisResult<()> { let pw = std::env::var("ZB_PASSWORD").expect("ZB_PASSWORD"); let url = format!("rediss://app:{pw}@valkey-7f3k.us-east.databasezy.com:6379/0"); let certs = TlsCertificates { client_tls: None, root_cert: Some(std::fs::read("databasezy-ca.pem").expect("read CA")), }; let client = Client::build_with_tls(url, certs)?; let mut conn = client.get_multiplexed_async_connection().await?; conn.set_ex::<_, _, ()>("hello", "world", 60).await?; let v: String = conn.get("hello").await?; println!("{v}"); Ok(())}Tested with: Valkey 9.1 · redis 0.27 (tokio-rustls-comp)
// One-time: keytool -importcert -noprompt -alias databasezy -file databasezy-ca.pem \// -keystore databasezy-truststore.p12 -storetype PKCS12 -storepass changeitimport io.lettuce.core.RedisClient;import io.lettuce.core.RedisURI;import io.lettuce.core.SslOptions;import io.lettuce.core.ClientOptions;import java.io.File;
public final class Cache { public static void main(String[] args) { var uri = RedisURI.Builder.redis("valkey-7f3k.us-east.databasezy.com", 6379) .withSsl(true) .withVerifyPeer(true) // chain + hostname .withAuthentication("app", System.getenv("ZB_PASSWORD").toCharArray()) .build(); var client = RedisClient.create(uri); client.setOptions(ClientOptions.builder() .sslOptions(SslOptions.builder() .truststore(new File("databasezy-truststore.p12"), "changeit").build()) .build()); try (var conn = client.connect()) { conn.sync().setex("hello", 60, "world"); System.out.println(conn.sync().get("hello")); } client.shutdown(); }}Tested with: Valkey 9.1 · Lettuce 6.5
using StackExchange.Redis;
var options = new ConfigurationOptions{ EndPoints = { { "valkey-7f3k.us-east.databasezy.com", 6379 } }, User = "app", Password = Environment.GetEnvironmentVariable("ZB_PASSWORD"), Ssl = true, SslHost = "valkey-7f3k.us-east.databasezy.com", // hostname verification};// If the CA is not in the OS store, trust it explicitly:options.TrustIssuer("databasezy-ca.pem");
var mux = await ConnectionMultiplexer.ConnectAsync(options);var db = mux.GetDatabase();await db.StringSetAsync("hello", "world", TimeSpan.FromSeconds(60));Console.WriteLine(await db.StringGetAsync("hello"));Tested with: Valkey 9.1 · StackExchange.Redis 2.8
<?php$client = new Predis\Client([ "scheme" => "tls", "host" => "valkey-7f3k.us-east.databasezy.com", "port" => 6379, "username" => "app", "password" => getenv("ZB_PASSWORD"), "ssl" => ["cafile" => "databasezy-ca.pem", "verify_peer" => true, "verify_peer_name" => true],]);$client->setex("hello", 60, "world");echo $client->get("hello");Tested with: Valkey 9.1 · predis 2.3
require "redis"
redis = Redis.new( url: "rediss://app:#{ENV.fetch('ZB_PASSWORD')}@valkey-7f3k.us-east.databasezy.com:6379/0", ssl_params: { ca_file: "databasezy-ca.pem", verify_mode: OpenSSL::SSL::VERIFY_PEER })redis.set("hello", "world", ex: 60)puts redis.get("hello")Tested with: Valkey 9.1 · redis-rb 5.3
valkey-cli --tls --cacert databasezy-ca.pem -h valkey-7f3k.us-east.databasezy.com -p 6379 --user app --askpass
# orzb connect valkey-7f3kTested with: Valkey 9.1 · valkey-cli 9.1
The Valkey connection guide covers multiplexed clients, blocking commands and persistence.
See Connecting to Databasezy for host names, the CA bundle and the allow-list, which work the same for every engine.
Migrate in
Section titled “Migrate in”You can bring an existing Valkey database in from these sources. Each links to a step-by-step guide.
| Source | How | Continuous sync | Guide status |
|---|---|---|---|
| Render | Connection string | No | Coming soon · phase 2 |
| Railway | Connection string | No | Coming soon · phase 2 |
| Heroku | Connection string, File upload | No | Coming soon · phase 2 |
| Aiven | Connection string | No | Coming soon · phase 2 |
| DigitalOcean Managed Databases | Connection string | No | Coming soon · phase 2 |
| Upstash Redis | Connection string | No | Available |
| Vercel KV (legacy, now Upstash) | Connection string | No | Coming soon · phase 2 |
| Redis Cloud | Connection string, File upload | No | Coming soon · phase 2 |
| Self-hosted server | Connection string, Local tools (zb migrate --from local) | No | Available |
| Local files and dumps | File upload, Local tools (zb migrate --from local) | No | Available |
| Docker container | Local tools (zb migrate --from local) | No | Available |
| Another Databasezy instance | Instance to instance | No | Coming soon · phase 2 |
Keys are copied with SCAN and DUMP/RESTORE, keeping their TTLs. There is no continuous sync for key-value
engines: keys written to the source after the copy starts may be missed, which is fine for caches but needs a short
freeze for queues and counters. Moving from Redis is covered in engine conversions.
How migrations work explains preflight, verification and cutover.
Backups and restore
Section titled “Backups and restore”Each backup copies an RDB snapshot streamed from the server plus the append-only file directory, and restores land on that backup. There is no point-in-time recovery: for data you cannot lose between backups, keep the source of truth in a database that has it.
Valkey backups use RDB + AOF. They run inside the instance's namespace, stream straight to the cell's object storage and are checksummed on upload. How often they run and how long they are kept follows your plan's backup policy. A backup is always taken before a resize or a version upgrade.
Point-in-time recovery is not available for Valkey. A restore returns the data as of a scheduled or manual backup. Restores create a new instance by default and leave the original untouched; an in-place restore asks you to type the instance name and takes a pre-change backup first.
zb backups create valkey-demo --label before-release # manual snapshotzb backups list valkey-demozb backups restore valkey-demo <backup-id> --name valkey-demo-restorePause and scale to zero
Section titled “Pause and scale to zero”Valkey can scale to zero. A paused instance has no running pods and bills no compute; its storage and backups are kept and billed as usual. Connections are refused until you resume it. On the Free plan an instance pauses by itself after 15 minutes without connections and wakes on the next one; the gateway holds that connection for up to 30 seconds while it starts.
zb instances pause valkey-demozb instances resume valkey-demoSee Pause and resume for schedules, wake times and billing while paused.
Limits and sizes
Section titled “Limits and sizes”Valkey runs on every size, including the Free plan's f0. The size sets the CPU, memory, storage ceiling and connection limit; the gateway refuses connections over the limit with a protocol error. Storage grows in steps up to the ceiling, and you can resize at any time.
| Size | vCPU | Memory | Max storage | Max connections | ≈ $ / month |
|---|---|---|---|---|---|
f0 | 0.063 | 512 MiB | 1 GB | 20 | Free |
s0 | 0.25 | 1 GiB | 20 GB | 60 | $10 |
s1 | 0.5 | 2 GiB | 50 GB | 100 | $15 |
s2 | 1 | 4 GiB | 200 GB | 200 | $60 |
m2 | 2 | 8 GiB | 500 GB | 400 | $110 |
m4 | 4 | 16 GiB | 1 TB | 800 | $210 |
l8 | 8 | 32 GiB | 4 TB | 1,500 | $410 |
l16 | 16 | 64 GiB | 8 TB | 3,000 | $960 |
xl32 | 32 | 128 GiB | 16 TB | 5,000 | $1,870 |
Full details, including hourly prices and burst CPU, are in the size catalogue; plan quotas are in limits and quotas.
Each instance caps its dataset at 75% of the size’s memory (maxmemory) with the noeviction policy: when the
instance is full, writes fail with OOM command not allowed when used memory > 'maxmemory' while reads and deletes keep
working, and keys are never evicted. The rest of the memory covers connection buffers and the copy made while
persistence snapshots run. Watch used_memory in INFO memory, set TTLs on cache keys, and resize before you reach
the cap.
Security
Section titled “Security”The instance has one user, default, with access to every command on its own instance: FLUSHALL, CONFIG SET
and Lua scripts work (DEBUG and MODULE stay off), and no ACL rules restrict it. Keep the password on your servers.
- TLS on every connection. TLS 1.2 is the minimum and TLS 1.3 is preferred; plaintext is never
offered. Verify the server, not just the encryption: use
rediss:// with hostname checking. See TLS and the CA bundle. - IP allow-list. The gateway checks the client address before authentication, on every plan.
Manage it under Network → Allow-list in the portal or with
PUT /v1/orgs/{org}/instances/{id}/network. - Credentials. Generated inside the cell, shown once, never stored by the control plane. Rotate them with an overlap window so nothing breaks.
- Secure hosting. Secure placement (HIPAA-ready) is a per-instance option once your organization has signed the BAA: dedicated nodes, customer-managed keys and immutable backups. See Secure hosting and the BAA.
- Staff access. Databasezy staff cannot read your data without a grant you issue. See data confidentiality.
Will my Redis client work?
Section titled “Will my Redis client work?”Yes. ioredis, redis-py, go-redis, Lettuce, StackExchange.Redis and other Redis clients speak the same protocol. Enable TLS and pass the password (with the username default if your client asks for one).
Are Redis modules such as RediSearch or RedisJSON available?
Section titled “Are Redis modules such as RediSearch or RedisJSON available?”No. They are not part of Valkey. When you migrate from Redis Cloud, preflight lists the keys that use module types.
Should I use a connection pool?
Section titled “Should I use a connection pool?”Usually not. One multiplexed client per process is the norm. Pub/sub subscribers and blocking commands each hold a connection of their own, so count them against the size’s limit.