Published: October 26, 2026 · by Srinu Desetti (creator & maintainer)
valkey-http: Valkey from Edge, Serverless and Browsers over HTTP
valkey-http is a zero-dependency fetch client for Valkey over HTTP. It runs anywhere fetch runs — Cloudflare Workers, Vercel Edge, Deno, Bun, browsers, and plain Node.js — because it never opens a TCP socket. Every command travels as an HTTP request to an HTTP-to-Valkey gateway, and the whole client ships as a handful of files with no runtime dependencies. I created and maintain this package as the edge-side half of the Valkey HTTP pair.
| Package | valkey-http (opens in a new tab) v0.1.0 |
| License | MIT |
| Runtime dependencies | 0 |
| Module format | ESM, TypeScript declarations included |
| Runtime | Any fetch runtime — edge, serverless, browsers; Node.js ≥ 18 |
| Source | github.com/webdevelopersrinu/valkey-http (opens in a new tab) |
The Problem: No Sockets at the Edge
Every classic Valkey client — iovalkey, node-redis ports, anything built on the RESP protocol — assumes one thing: it can open a raw TCP socket to the server and keep it alive. That assumption quietly fails in exactly the environments modern applications are moving to:
- Edge runtimes can't open TCP sockets. Cloudflare Workers, Vercel Edge Functions, and similar V8-isolate platforms expose
fetchand little else. There is nonet.Socket, so a RESP client cannot even connect. - Serverless penalizes persistent connections. Even where sockets exist (AWS Lambda, traditional serverless Node), a connection pool per short-lived instance means connection storms against the server and cold-start latency paid on every invocation.
- Browsers never had sockets at all. Any client-side code that wants to touch a cache must go through HTTP anyway.
In all three, HTTP is not merely an option — it is the only transport available. That is the entire premise of valkey-http: if fetch is the one primitive every runtime shares, the Valkey client should be built on fetch and nothing else.
The client is stateless by design. There is no connection to establish, keep alive, or pool — each command is one HTTP request, which is precisely the lifecycle model edge and serverless platforms are built around.
How It Works: Commands over HTTP
A classic client speaks RESP over a socket; valkey-http speaks JSON over HTTP. Each command becomes a request to the gateway, the gateway executes it against the real Valkey server over TCP, and the reply comes back as the response body.
Browser / Edge / Serverless Your infrastructure
┌─────────────────────┐ HTTPS ┌──────────────────┐ TCP/RESP ┌────────┐
│ valkey-http (fetch) │ ────────▶ │ HTTP gateway │ ───────────▶ │ Valkey │
│ zero dependencies │ ◀──────── │ (valkey-http- │ ◀─────────── │ server │
└─────────────────────┘ │ server) │ └────────┘
└──────────────────┘The server half of that diagram is its own package: valkey-http-server — the HTTP-to-Valkey gateway you deploy next to your Valkey instance. The two packages are designed as a pair: the client assumes the gateway's request/response contract, and the gateway holds the real TCP connections so your edge code never has to.
Because authentication is a bearer token on each request rather than an AUTH handshake on a socket, the same client works unchanged in a browser tab, a Worker, and a Node process — the only per-environment difference is where the token comes from.
Design Notes — Decisions I Kept and Why
Zero dependencies, by construction
The entire client is built on the fetch global — no HTTP library, no protocol parser, no polyfills. The published package is four files and about 5 KB unpacked. In edge environments, where every kilobyte of bundle counts against cold-start time and platform size limits, a dependency tree is a liability; here there is none to audit, none to tree-shake, none to break.
ESM-only, Node ≥ 18
fetch became a stable global in Node.js 18, which makes 18 the natural floor: below it the package's one platform assumption does not hold. Shipping ESM-only keeps the module graph identical across Node, Deno, Bun, and bundlers targeting edge runtimes — one build, no dual-package hazard.
Stateless client, stateful gateway
Connection management is deliberately not the client's job. The gateway (valkey-http-server) owns the persistent TCP connections to Valkey, sitting in infrastructure where sockets are cheap and long-lived. The client stays a thin, stateless command mapper — which is why it can run in a browser tab and a Worker with the same code path.
HTTP semantics over protocol cleverness
Each command is an ordinary HTTP request, which means every piece of standard HTTP infrastructure works for free: CDN-level caching rules, request logging, per-route authentication, rate limiting at the gateway, and observability through tools that already understand HTTP. A latency cost per command is the honest trade — the FAQ below covers when that trade is right.
This is a solo project — I designed, built, and maintain valkey-http independently as the edge-side half of the Valkey HTTP pair.
What's Next?
valkey-http is only half the story. The other half is the gateway it talks to — the HTTP server that translates requests into real RESP commands against your Valkey instance.
← Back to Open Source overview
Continue to valkey-http-server — the HTTP-to-Valkey gateway →
Frequently Asked Questions
Why not just use a regular Valkey client like iovalkey?
If you run on a platform with TCP sockets and long-lived processes — a VM, a container, a classic Node server — you should: a socket client is faster per command. valkey-http exists for the platforms where that is impossible: Cloudflare Workers, Vercel Edge, and browsers expose fetch and no socket API at all. There, HTTP is not a preference but the only transport, and valkey-http is a client built honestly on that constraint.
Doesn't HTTP add latency compared to RESP over TCP?
Per command, yes — an HTTP request carries more overhead than a pipelined RESP frame on a warm socket. But the comparison at the edge is not HTTP versus a socket; it is HTTP versus nothing, because the socket option does not exist. And in serverless, the socket client pays its own hidden costs: connection setup on cold starts and connection storms under scale-out, which a stateless HTTP request avoids entirely.
Do I need valkey-http-server, or can I point this at Valkey directly?
You need the gateway. Valkey itself speaks RESP over TCP and has no HTTP listener, so something must translate — that is valkey-http-server, deployed next to your Valkey instance inside your infrastructure. The pair is split deliberately: the gateway holds the stateful TCP connections where sockets are cheap, and the client stays a zero-dependency fetch wrapper that runs anywhere.
Is it safe to call this from a browser?
The transport is fine — it is ordinary HTTPS — but treat the token like any client-exposed credential. A token shipped to a browser can issue whatever commands the gateway allows it, so scope it: expose only the commands and key patterns that are safe for untrusted callers, or keep browser traffic behind your own API route that holds the token server-side. For edge and serverless code the token stays in environment secrets, which is the common case.