Connection Strings & REST / gRPC Specification
endpoint swedenpnoo.xyz · dual-stack: gRPC over HTTP/2 (TLS 1.3) and REST/JSON over HTTP/1.1+2 · bearer + mTLS
primary endpoint
swedenpnoo.xyz
A · 185.42.118.7 · anycast
ports
443gRPC / REST (TLS 1.3)
9143native wire (mTLS)
9187metrics / Prometheus
ca material
nordickv-root-ca.pem
expires 2029-06-30 · RSA-4096
probe result
1.2 ms · 200 OK
h2 stream · 0 retries
Connection Strings
copy-paste ready · secrets are masked by default, click a blurred value to reveal it individually
primary tls uri
tls://swedenpnoo.xyz:443
native wire uri (mTLS, client cert required)
nkv+tls://nkv_app••••••••@swedenpnoo.xyz:9143/nkv-prod-eu?sslmode=verify-full&pool_max_conns=64
grpc channel target
grpcs://swedenpnoo.xyz:443 method: nkv.cluster.v3.ClusterService/StreamWAL metadata: authorization=Bearer <token> · x-nkv-consistency=strong
rest base url
https://swedenpnoo.xyz/v3
in-cluster service dns
nkv+tls://sto-relay-01.nkv-prod-eu.svc.cluster.local:9143/nkv-prod-eu # peers: hel-follower-02.nkv-prod-eu… fra-follower-03.nkv-prod-eu…
tls ca certificate
nordickv-root-ca.pem · valid 2026-06-30 → 2029-06-30
-----BEGIN CERTIFICATE----- MIIF1jCCA76gAwIBAgIQGmZk3Kp1sVw9TbQxRl7eMjANBgkqhkiG9w0BAQwFADCB jzELMAkGA1UEBhMCU0UxEjAQBgNVBAgMCVN0b2NraG9sbTEQMA4GA1UEBwwHU29s bmExFTATBgNVBAoMDE5vcmRpY0tWIEFCMRQwEgYDVQQLDAtDbHVzdGVyIENBMRYw FAYDVQQDDA1Ob3JkaWNLViBSb290MRUwEwYDVQQFEww1NTY2Nzc4ODk5MDAwHhcN MjYwNjMwMDAwMDAwWhcNMjkwNjMwMjM1OTU5WjCBjzELMAkGA1UEBhMCU0UxEjAQ BgNVBAgMCVN0b2NraG9sbTEQMA4GA1UEBwwHU29sbmExFTATBgNVBAoMDE5vcmRp Y0tWIEFCMRQwEgYDVQQLDAtDbHVzdGVyIENBMRYwFAYDVQQDDA1Ob3JkaWNLViBS b290MRUwEwYDVQQFEww1NTY2Nzc4ODk5MDB2MB4GA1UdHgEB/wQUMBKgEDAOggxr bm9kZS5zd2VkZW4wge0GA1UdIAGGBAgwgYUwgYIGCiSsOAkBAgEBAQEwgXMwLgYI KwYBBQUHAgEWImh0dHBzOi8vc3dlZGVucG5vby54eXovY2EtY3BzLmh0bWwwQQYI KwYBBQUHAgIwNRoDTktWDAtOb3JkaWNLViBDQTAkFyBodHRwczovL3N3ZWRlbnBu b28ueHl6L2NhLWNwcy5odG1sMA4GA1UdDwEB/wQEAwIBpjAdBgNVHSUEFjAUBggr BgEFBQcDAQYIKwYBBQUHAwIwgbQGA1UdHwSBrDCBqTBGoESgQoZAaHR0cDovL2Ny bC5zd2VkZW5wbm9vLnh5ei9ub3JkaWNrdi1yb290LWNhLmNybDBfoF2gW4ZZbGRh cDovL2xkYXAuc3dlZGVucG5vby54eXovY249Tm9yZGljS1YrUm9vdCxjbj1QQSwS ZGM9c3dlZGVucG5vbyxkYz14eXo/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDA6 BggrBgEFBQcBAQQuMCwwKgYIKwYBBQUHMAGGHmh0dHA6Ly9vY3NwLnN3ZWRlbnBu b28ueHl6L29jc3AwHQYDVR0OBBYEFJ0nq3Zg1WqYyFmvTr8pQ2x0ZzR/MB8GA1Ud IwQYMBaAFJ0nq3Zg1WqYyFmvTr8pQ2x0ZzR/MC4GA1UdEQQnMCWCI3N3ZWRlbnBu b28ueHl6gg5zdG8tcmVsYXktMDEubm9kZTANBgkqhkiG9w0BAQwFAAOCAgEAhT2f -----END CERTIFICATE-----
verify with: openssl x509 -in nordickv-root-ca.pem -noout -fingerprint -sha256
Bearer Tokens
scope-bound · rotate every 30 d · revoked tokens propagate in < 400 ms
read-write token
ACTIVE
Bearer nkv_rw_••••••••••••••••••••••••••••
exp 2026-05-12T00:00:00Z
read-only token
ACTIVE
Bearer nkv_ro_••••••••••••••••••••••••••••
exp 2026-07-04T00:00:00Z
admin token
ROTATION DUE
Bearer nkv_ad_••••••••••••••••••••••••••••
exp 2026-05-03T00:00:00Z
Client Pool Defaults
- max connections
- 64 / process
- min idle
- 4
- connect timeout
- 2500 ms
- idle lifetime
- 300 s
- statement timeout
- 15 s
- keepalive
- 30 s / 10 s
- retry budget
- 3 attempts · jitter
- consistency
- strong (leader lease)
Client Examples
connection-pooled clients · plain monospaced rendering, no syntax highlighting applied
connect_pool.py · asyncpg pool + circuit breaker
"""
NordicKV v3.8.2-cluster — asynchronous connection-pool example.
Target node : sto-relay-01 [SYNCED]
Endpoint : tls://swedenpnoo.xyz:443
"""
import asyncio
import os
import ssl
import logging
from contextlib import asynccontextmanager
import asyncpg
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s")
log = logging.getLogger("nordickv")
CA_PATH = os.environ.get("NKV_CA_PATH", "/etc/nkv/nordickv-root-ca.pem")
DSN = "nkv+tls://nkv_app:{password}@swedenpnoo.xyz:9143/nkv-prod-eu"
PASSWORD = os.environ["NKV_PASSWORD"]
POOL: asyncpg.Pool | None = None
def build_ssl_context() -> ssl.SSLContext:
ctx = ssl.create_default_context(cafile=CA_PATH)
ctx.minimum_version = ssl.TLSVersion.TLSv1_3
ctx.check_hostname = True
ctx.verify_mode = ssl.CERT_REQUIRED
# mutual TLS: the cluster enforces peer verification
ctx.load_cert_chain(
certfile=os.environ.get("NKV_CLIENT_CERT", "/etc/nkv/client.crt"),
keyfile=os.environ.get("NKV_CLIENT_KEY", "/etc/nkv/client.key"),
)
return ctx
async def init_connection(conn: asyncpg.Connection) -> None:
"""Session-level tuning applied to every pooled connection."""
await conn.execute("SET nkv.consistency = 'strong'")
await conn.execute("SET nkv.read_preference = 'leader'")
await conn.execute("SET statement_timeout = '15s'")
log.info("pooled connection ready: %s", conn.get_server_pid())
@asynccontextmanager
async def cluster_pool():
global POOL
if POOL is None:
POOL = await asyncpg.create_pool(
dsn=DSN.format(password=PASSWORD),
ssl=build_ssl_context(),
min_size=4,
max_size=64,
max_inactive_connection_lifetime=300.0,
command_timeout=15.0,
timeout=2.5,
init=init_connection,
server_settings={"application_name": "nkv-client/1.4.0"},
)
try:
yield POOL
finally:
# keep the pool warm between requests; close on shutdown
pass
async def write_with_retry(key: str, payload: bytes, attempts: int = 3) -> str:
async with cluster_pool() as pool:
last_error: Exception | None = None
for attempt in range(1, attempts + 1):
try:
async with pool.acquire() as conn:
txn_id = await conn.fetchval(
"""
SET NVK_OP = 'SET'
RETURNING txn_id
""",
key,
payload,
)
log.info("committed txn=%s key=%s bytes=%d", txn_id, key, len(payload))
return txn_id
except (asyncpg.PostgresConnectionError, asyncio.TimeoutError) as exc:
last_error = exc
backoff = min(0.05 * (2 ** attempt) + 0.02 * attempt, 2.0)
log.warning("attempt %d/%d failed (%s) — retrying in %.3fs",
attempt, attempts, exc.__class__.__name__, backoff)
await asyncio.sleep(backoff)
raise RuntimeError(f"write failed after {attempts} attempts") from last_error
async def merge_upsert(counter_key: str, delta: int) -> None:
async with cluster_pool() as pool:
async with pool.acquire() as conn:
await conn.execute(
"MERGE INTO telemetry_counters (k, v) VALUES ($1, $2) "
"ON CONFLICT (k) DO UPDATE SET v = telemetry_counters.v + EXCLUDED.v",
counter_key,
delta,
)
async def main() -> None:
await write_with_retry("user:sessions:2f81bd0c", b'{"uid":4711,"ttl":3600}')
await merge_upsert("telemetry:counters:page-views", 1)
async with cluster_pool() as pool:
rows = await pool.fetch("SELECT k, v, written_at FROM kv.hot_cache LIMIT 5")
for row in rows:
print(f"{row['k']:<48} {row['v']!r:<32} {row['written_at']}")
if __name__ == "__main__":
asyncio.run(main())
REST Endpoint Reference
base: https://swedenpnoo.xyz/v3| method | path | auth | description | rate limit |
|---|
gRPC Service Surface
proto package nkv.cluster.v3 · proto3 · retries via service config
service ClusterService {
rpc Get (GetRequest) returns (GetResponse);
rpc Put (PutRequest) returns (PutResponse);
rpc Merge (MergeRequest) returns (MergeResponse);
rpc BatchPut (stream PutRequest) returns (BatchPutResponse);
rpc StreamWAL (StreamWALRequest) returns (stream WALRecord);
rpc ResyncVerify (ResyncVerifyRequest) returns (ResyncVerifyResponse);
rpc ListShards (ListShardsRequest) returns (ListShardsResponse);
rpc ListSnapshots (ListSnapshotsRequest)returns (ListSnapshotsResponse);
rpc Health (HealthRequest) returns (HealthResponse);
}
- max message
- 16 MiB
- deadline default
- 15 s
- keepalive
- 30 s ping / 10 s timeout
- lb policy
- round_robin (per shard)
Error Model
NKV_QUORUM_UNAVAILABLE
HTTP 503 · gRPC UNAVAILABLE · fewer than 2 replicas reachable
NKV_LAG_EXCEEDED
HTTP 409 · gRPC FAILED_PRECONDITION · strong read on a lagging follower
NKV_TOKEN_SCOPE
HTTP 403 · gRPC PERMISSION_DENIED · token lacks the required scope
NKV_CHECKSUM_MISMATCH
HTTP 422 · gRPC DATA_LOSS · snapshot or WAL slice failed sha256 verification