Connect with verified TLS and RESP2
The endpoint is rediss://91.99.35.23:6380. TLS terminates at the storage gateway. Use AUTH <credential-id> <secret>. Database 0 maps to your cache instance; other databases are rejected.
Create a cache and a credential in the console. The secret appears once. Store it in your application’s secret manager. Credentials belong to the exact identity link used to create them. Unlinking permanently revokes those credentials, including after relinking.
redis-cli
Use a local TLS tunnel that verifies both the certificate chain and the gateway IP. Save this Linux stunnel configuration as pipe-kv.conf, then run stunnel pipe-kv.conf. Adjust the CA directory for your operating system. See the stunnel manual.
foreground = yes
client = yes
[pipe-kv]
accept = 127.0.0.1:16380
connect = 91.99.35.23:6380
verifyChain = yes
CApath = /etc/ssl/certs
checkIP = 91.99.35.23In a second terminal, connect redis-cli through the tunnel:
redis-cli -2 -h 127.0.0.1 -p 16380 \
--user "$PIPE_KV_CREDENTIAL_ID" --askpass
SET example hello PX 60000
GET example
PTTL example
DEL examplePython: redis-py
import os
import redis
from redis.backoff import NoBackoff
from redis.retry import Retry
cache = redis.Redis(
host="91.99.35.23", port=6380, ssl=True,
ssl_cert_reqs="required", ssl_check_hostname=True,
username=os.environ["PIPE_KV_CREDENTIAL_ID"],
password=os.environ["PIPE_KV_SECRET"],
db=0, protocol=2, decode_responses=False,
socket_connect_timeout=5, socket_timeout=5,
retry=Retry(NoBackoff(), 0),
)
cache.set(b"example", b"hello", px=60000)
assert cache.get(b"example") == b"hello"
cache.delete(b"example")
# For pipelines: cache.pipeline(transaction=False)These examples explicitly select RESP2 and turn off automatic operation retries. See the redis-py connection reference.
JavaScript: node-redis
import { createClient } from 'redis';
const cache = createClient({
url: 'rediss://91.99.35.23:6380',
username: process.env.PIPE_KV_CREDENTIAL_ID,
password: process.env.PIPE_KV_SECRET,
database: 0,
RESP: 2,
disableOfflineQueue: true,
commandsQueueMaxLength: 32,
socket: { reconnectStrategy: false },
});
cache.on('error', console.error);
await cache.connect();
await cache.set('example', 'hello', { PX: 60000 });
console.log(await cache.get('example'));
await cache.del('example');
await cache.close();Keep TLS certificate verification enabled. See the node-redis configuration reference.
JavaScript numbers lose precision outside the safe integer range. For full 64-bit counter results, import RESP_TYPES and use cache.withTypeMapping({ [RESP_TYPES.NUMBER]: String }). Convert those decimal strings to BigInt when needed. For binary values, map RESP_TYPES.BLOB_STRING to Buffer.
Supported commands
| Capability | Commands |
|---|---|
| Strings | GET; SET with NX or XX and EX or PX; SETEX; PSETEX |
| Multiple keys | Atomic-snapshot MGET; variadic DEL and EXISTS |
| Expiration | TTL, PTTL, EXPIRE, PEXPIRE, PERSIST |
| Counters | INCR, INCRBY, DECR, DECRBY |
| Discovery | SCAN with MATCH and COUNT |
| Connections | AUTH, PING, ECHO, QUIT, SELECT 0, COMMAND, HELLO 2, CLIENT GETNAME/SETNAME/SETINFO |
Keys and values are binary safe. Counters use atomic signed 64-bit arithmetic, reject overflow, and retain the key’s existing expiration. Expiration has millisecond precision. DEL counts each existing key once in its result; EXISTS counts each requested occurrence. MGET returns one snapshot, including duplicate keys.
Unsupported commands and options fail before mutation. MSET, transactions, Lua, Pub/Sub, complex data types, Cluster, and RESP3 are unavailable. Use nontransactional pipelines. SCAN is scoped to your cache and can return an empty page with a nonzero cursor. Continue until the cursor is 0.
Wire framing follows the Valkey RESP2 protocol specification. This command subset does not imply full Redis or Valkey compatibility.
Initial limits
- One cache per credit wallet; 64 MiB per cache, including keys, values, indexes, expiry metadata, and retained response buffers.
- Sixteen instances share a 1 GiB node arena. Each instance evicts its own least recently used entries.
- Keys up to 1 KiB; values up to 1 MiB.
- At most 128 requested keys per multi-key command and 8 MiB per response.
- SCAN examines at most 256 entries per call. COUNT is a bounded work hint.
- 256 connections and up to 32 active commands at the gateway, subject to memory admission and backpressure.
Prepaid pricing
One USDC atom per committed key operation: $1 per million operations. GET and MGET also charge committed value bytes at the versioned read rate shown in the console. Framing, uploads, internal traffic, and replication are excluded.
Misses and unmet NX/XX conditions count. Multi-key commands count every requested key, including duplicates. SCAN counts once per call. Connection setup and bounded capability discovery are free, as are definite rejections before commitment. Fractional read charges accumulate across settlements without per-command rounding.
A committed operation remains billable if its response is lost. Short credit reservations share your existing storage balance; unresolved usage can temporarily hold credit until reconciliation.
Errors and recovery
Cache data may expire, be evicted, or disappear after a restart. Keep authoritative copies in durable storage and treat a miss as a normal application event.
On NOAUTH, renew authentication or rotate a revoked credential. On NOCREDIT, check available credit and unsettled reservations. TRYAGAIN indicates temporary admission or accounting pressure.
UNKNOWN or COMMITTED without a response means the operation might already have executed. Do not automatically retry counters or other state changes. Use application-level reconciliation. A new connection is not proof that a preceding operation failed.
Cold recovery uses a new empty generation on an explicitly assigned node. Automatic gateway failover is outside this release. Latency and mixed-load performance gates are release targets, not current performance claims.