kdb as unified data plane

draft

stackRFC001 — kdb as unified data plane

Abstract

kdb-next (TiKVbacked, RFC001 of kdb-next) evolui de "replacement relacional do kdbGo atual" para *ubstrate primário multimodel unificado da Koder Stack* Layers especializadas (relational, time-series, KV, vector, search, stream) compartilham o mesmo substrate distribuído (TiKV + MVCC + Raft + Percolator) e ganham ACID cross-model nativo. Componentes Koder param de manter Redis/ Timescale/Elasticsearch separados; passam a falar com kdb-next através de drivers SQL ou protocol-specific shims.

Três stores ficam *egitimamente fora*do kdb-next:

  • *kdrive`*(object storage, S3compat): blobs > 1 MB, petscale
  • *edis local*em hot paths que provadamente exigem < 1ms p99
  • *RDT layer*(Yjs/Automerge) pra collaborative state com

    consistência eventual

Pra *udo o resto*(sessões, rate-limit counters, métricas, search index, audit logs, telemetry, vector embeddings, stream events), kdb-next é o destino.

Motivation

O problema atual

A Koder Stack hoje (20260509) tem ~7 storage tiers diferentes em produção:

  • *ostgres*(kdb 18.3) em LXC kdb — relational principal
  • *imescaleDB*em LXC kbull — time-series
  • *edis*em alguns LXCs (sessões kbot, hot caches)
  • *inIO*em LXC kdrive — S3-compat blobs
  • *db-next*em desenvolvimento (LXCs futuros) — relational

    hyperscale

  • *ilesystem*em vários componentes — flat-file state
  • *nmemory*maps em alguns serviços — nãopersistent state

Cada tier tem:

  • Backup separado, com falhas correlacionadas em incidentes
  • Auth model próprio (Postgres roles, Redis ACLs, MinIO IAM)
  • Monitoring/alerting separado
  • Failure modes incompatíveis (Postgres ACID vs Redis eventually-

    consistent vs filesystem unreliable)

  • Migration path único por tier (mexer em schema → 7× operação)

Cross-tier transactions são *mpossíveis*— uma operação que escreve credentials no kdb e invalida cache no Redis pode falhar no meio: cache stale + DB consistent. Cada componente reinventa saga / outbox pattern.

A vision

kdb-next (TiKV) substrate unificado, com *ayers*específicas servindo cada padrão de acesso. Mesmo MVCC + Raft, mesmo backup, mesmo auth model, mesmo monitoring, *ransactions cross-model ACID nativo*

O pattern é *iDB ecosystem*aplicado à Koder Stack:

TiDB ecosystem:        Koder Stack equivalente:
  TiKV   ─── KV          kdb-kv      (KV nativo, expor TiKV)
  TiDB   ─── SQL         kdb-next    (relational SQL)
  TiFlash─── OLAP        kdb-flash   (column-store, futuro)
  TiCDC  ─── change      kdb-cdc     (Raft log → consumers)

Plus layers específicas Koder:

  kdb-ts      time-series  (hypertable-style sobre TiKV ranges)
  kdb-vec     vector       (ANN sobre TiKV-stored embeddings)
  kdb-search  full-text    (Lucene-style index, derivado via CDC)
  kdb-stream  pub/sub      (Raft log → fan-out subscribers)

Result: *m substrate, sete interfaces* ACIDcrosseverything.

Goals

  • Substrate único pra *oda persistent data*em apps Koder (com 3

    exceções listadas em §Non-goals)

  • Multimodel (relational, KV, timeseries, vector, search, stream)

    sobre o mesmo TiKV

  • ACID crossmodel nativo (escrever em timeseries + atualizar

    contador KV + emitir evento no stream = uma transação)

  • Multitenantbydefault (alinhado com `policies/multitenant-

    by-default.kmd`)

  • Multicluster + multiregion + active-active (alinhado com

    kdb-RFC-008 + kdb-RFC-009)

  • HA (Raft replication, auto-failover)
  • Read replicas (alinhado com kdb-RFC-011)
  • Hyperscale (100M+ tenants target, alinhado com kdb-RFC-001)
  • Operações simplificadas: 1 backup process, 1 monitoring stack,

    1 auth model

Nongoals (stay outside kdbnext)

Estas três categorias *ão convergem*pro substrate, por design:

1. Object/blob storage

Bytes grandes (release artifacts > 1 MB, attachments, build outputs, user uploads, container images, video frames, audio waveforms) ficam em kdrive (MinIO ou sucessor S3-compat).

Razão técnica: TiKV não é otimizado pra blobs. Replicação Raft de um blob 100MB satura I/O sem ganho — Raft consensus pra dado que não muda é overkill. GC de blobs MVCC é complexo. Object store dedicado é pattern correto.

Coordenação: kdbnext armazena *etadata + ACL + signedURL config* kdrive serve bytes. É o pattern S3 + Postgres bem estabelecido.

2. Edge cache (sub-ms hot paths)

Onde p99 < 1ms é requisito real e não negociável:

  • Auth token → user_id resolution (toda request passa por aí)
  • Rate-limit counters (incrementar em < 100µs)
  • Presence indicators (collaborative cursors, online users)

Estes ficam em *edis local in-process do componente* com keys prefixadas por tenant (tenant:<uid>:<key>).

kdbnext é *ource of truth* Redis é readthrough cache + write queue, com TTL agressivo (segundos) e invalidação pelo CDC quando kdb-next muda.

Critério: hot path deve ser *rovadamente*> 100× mais frequente que cold path **atender p99 < 5ms para justificar Redis. Caso contrário, kdb-next direto basta.

3. CRDT collaborative state

Live presence, OT cursors, real-time editing — modelo de consistência é eventual + merge functions. Forçar transações ACID adiciona latência demais e quebra o pattern.

Solução: Yjs/Automerge layer (inprocess percomponent, sincroniza P2P entre clients via WebSocket). Snapshot persistido em kdb-next periodicamente (cada N segundos ou no save explícito do user).

High-level architecture

┌──────────────────────────────────────────────────────────────────────┐
│ Application APIs                                                      │
│ (kode, hub, flow, kortex, gateway, jet, id, kbot, talk, drive, …)    │
└────────────────────────────┬─────────────────────────────────────────┘
                             │
            ┌────────────────┼────────────────┐
            ▼                ▼                ▼
       SQL driver      KV driver        TS driver
       (relational     (cache, hot      (metrics,
        + transac-      counters)        audit, logs)
        tions)
            │                │                │
            └────────────────┼────────────────┘
                             ▼
            ┌────────────────────────────────────┐
            │ kdb-next adapter layer             │
            │  - SQL parser/planner              │
            │  - KV expose                       │
            │  - TS hypertable layer             │
            │  - Vec ANN layer                   │
            │  - Search index (derived via CDC)  │
            │  - Stream (Raft log → fan-out)     │
            └────────────────┬───────────────────┘
                             ▼
            ┌────────────────────────────────────┐
            │ TiKV substrate                     │
            │  - MVCC                            │
            │  - Raft replication (3+ nodes)     │
            │  - Percolator distributed txn      │
            │  - PD (placement driver, multi-    │
            │    region geo-aware sharding)      │
            └────────────────────────────────────┘
                             │
                             ▼
                   ┌─────────────────┐ ┌─────────────────┐
                   │ kdrive          │ │ Redis local     │
                   │ (S3-compat blob)│ │ (hot cache,     │
                   │                 │ │  source-of-     │
                   │ kdb-next holds  │ │  truth in       │
                   │ metadata + ACL  │ │  kdb-next)      │
                   └─────────────────┘ └─────────────────┘

Layers detalhadas

Layer 1 — kdb-next SQL (relational)

Status: em desenvolvimento (RFC001 do kdbnext; shadow-active).

Surface: SQL completo, drivers Postgres-compatible (apps falam SQL via lib pgxpqetc. sem mudanças).

Use cases:

  • User accounts (Koder ID)
  • Repositories (Flow)
  • Workspaces, memberships
  • Credentials (FLOW-003 hierarchy)
  • Permissions, ACLs
  • Tudo que tem queries com JOIN, GROUP BY, transações

ACID: full MVCC, distributed transactions via Percolator.

Layer 2 — kdb-kv (KV nativo)

Status: planejado (este RFC).

Surface: API estilo Redis (GET/SET/DEL/EXPIRE/HGET/SADD) ou native TiKV client.

Use cases (que hoje usam Redis):

  • Sessões SSO
  • Rate-limit counters
  • Background job queues (com transações pra garantir delivery)
  • Distributed locks (TiKV native suporta isso)
  • Session-presence (tracked com TTL)

Diferença vs Redis local: persistência + cross-region replication + ACID com outras layers. Latência: ~1-2ms vs ~50µs do Redis local.

*uando usar kdb-kv vs Redis local* ver §Non-goals item 2.

Layer 3 — kdb-ts (time-series)

Status: planejado (parcial em kdb-RFC-007).

Surface: hypertable-style API, similar ao TimescaleDB. Particionamento automático por tempo + tenant.

Use cases:

  • Token usage tracking (rate_limit observations) — *aso direto que

    motiva esta RFC*

  • Métricas Prometheus (component health, request rates)
  • Audit logs com retention
  • Telemetry de apps clients (kode/app, kbot)
  • Activity feeds (Koder ID profile activity)

Features:

  • Continuous aggregates (rollups)
  • Compression de chunks > 7 dias (factor ~10×)
  • Retention policies per-tenant
  • TimescaleDB-compat query syntax (gradual migration de kbull)

Layer 4 — kdb-vec (vector / ANN)

Status: planejado (futuro, sem RFC ainda).

Surface: API similar a pgvector ou Milvus.

Use cases:

  • Embeddings de docs pra search semantic (Krep, Kortex)
  • Embeddings de prompts/responses pra Claude history search
  • Recommendations (Hub package similarity)

Trade-off: layer dedicada (Milvus) é mais performática em escala massive (>100M vectors); kdb-vec basta pra <10M. Reavalia quando hit.

Layer 5 — kdb-search (full-text + structured)

Status: planejado (depois de kdb-vec).

Surface: query API similar a Elasticsearch.

Implementação: index Lucene-style *erivado*de tabelas relational via CDC. Quando uma row no Flow muda, índice atualiza. Latência de indexação: ~ms (singleregion) ou ~100ms (crossregion).

Use cases:

  • Full-text search no Hub (apps, skills)
  • Code search complementar ao koder-krep (que cobre on-disk grep)
  • Search em issues, PRs, comments do Flow

Layer 6 — kdb-stream (pub/sub + change capture)

Status: planejado.

Surface:

  • Producer: TiKV Raft log → topic (toda mutation cabe em event)
  • Consumer: subscribe a topic via gRPC streaming

Use cases:

  • CDC pra fora (cliente integrações, ETL pra warehouse)
  • Webhooks (Flow webhooks ficam aqui em vez de table polling)
  • Notification fan-out (Hub release → notify followers)
  • Build trigger queues (commit → CI runner)

Substitui Kafka pra cargas internas. Externos (clientes B2B com Kafka existente) podem consumir via mirror.

Multi-tenancy alignment

Esta RFC e policies/multi-tenant-by-default.kmd são *omplementares*

  • A policy diz "todo dado tem koder_user_id/workspace_id"
  • Esta RFC diz "e o substrate único onde cada layer implementa

    isolamento na sua linguagem nativa é kdb-next/TiKV"

Cada layer implementa isolation conforme spec specs/multi-tenancy/contract.kmd:

Layer Isolation
kdb-next SQL Postgres-style RLS via current_setting('koder.uid')
kdb-kv Key prefix obrigatório (tenant:<uid>:)
kdb-ts Hypertable index (koder_user_id, time) + RLS
kdb-vec Filter por metadata {tenant: <uid>} em ANN
kdb-search Index per-tenant ou global com filter mandatory
kdb-stream Topic naming tenant.<uid>.<resource>

Cross-tenant queries: *rror by default* Admin path explícito com audit.

Multi-region

Alinhado com kdb-RFC-008 (multiregion replication) e `kdbRFC-009` (active-active).

Topology esperada (long-term):

  • 3+ regiões geográficas (ex: SP, EU, US)
  • Cada tenant tem *ome region*(storage primary)
  • Replicação assíncrona pra outras regiões (readonly crossregion)
  • Active-active permite escrever em qualquer região; conflitos

    resolvidos via Lamport timestamps + LWW perkey (ou CRDTlike merges).

PD (Placement Driver) gerencia placement consciente de tenant home region.

HA

Alinhado com kdb-RFC-001 + kdb-RFC-011:

  • 3+ Raft replicas por shard (default 3, configurável 5 pra crítico)
  • Auto-failover < 5s
  • Read replicas standby (kdbRFC011) pra cargas pesadas de read
  • Backup contínuo via incremental WAL streaming pra object storage

Roadmap fasings

*ase atual = 0*(consolidação). kdbnext em shadowactive, RFC001 do kdbnext + RFC007 (timeseries) + RFC008 (multi-region) + RFC009 (activeactive) + RFC-011 (read replicas) já desenhados. Layers KV, vector, search, stream ainda em conceito.

Fase 0 — hoje (consolidação relational)

  • kdbnext em shadowactive no monorepo
  • Postgres kdb corrente serve produção
  • 5 RFCs do kdb-next ratificadas (architecture, timeseries,

    multiregion, activeactive, read-replicas)

Fase 1 — próximos 6 meses (kdb-next primary relational)

  • Flip kdb-next pra primary em *odos*componentes que usam Postgres
  • Foundation/id já tá nele; flow, hub, kortex seguem
  • Aposentar kdb (Postgres) — preservado pra recovery, não rota ativa

Fase 2 — kdbts (timeseries unified)

  • services/ai/gateway token-usage tracker (proposta inicial deste

    RFC) é o *aso piloto*

  • Migrar kbull (TimescaleDB) pra kdb-ts
  • Métricas Prometheus passam por kdb-ts
  • Activity feeds, audit logs

Fase 3 — kdb-kv + Redis aposentadoria

  • Sessions, ratelimit counters, queues migram pra kdbkv
  • Redis fica só onde *rovadamente*justificado por p99 < 1ms

    (auth token resolution, hot ratelimit) — com kdbnext como source- of-truth

Fase 4 — kdbsearch + kdbstream + kdb-vec

  • Search Hub passa pra kdb-search
  • Webhook delivery passa pra kdb-stream
  • Vector search semantic passa pra kdb-vec (ou Milvus se escala

    exige)

Fase 5 — full convergência

  • Único storage stack: kdbnext + kdrive + Redisemedgecases-

    específicos

  • 1 backup process, 1 monitoring stack, 1 auth model
  • Cross-model transactions usadas livremente

Tempo estimado realista: *-5 anos*com team focado. Comparáveis:

  • TiDB ecosystem maturou em ~7 anos (2015 → 2022)
  • Spanner ~5 anos antes do paper (2007 → 2012)
  • FoundationDB ainda evolui após 2015

Promotion gates (per-layer)

Cada layer (kdbkv, kdbts, etc.) só vira default na Stack quando passar pelos * gates*de policies/self-hosted-first.kmd:

  1. *eature parity* cobre todos use cases do incumbent
  2. *erformance* bench a la koder-bench mostra kdb-<layer>

    incumbent em workload representativo

  3. *tability* 30 dias em prd shadow-active sem regressão
  4. *apability* features novas que o incumbent não tem (ACID

    crossmodel, multiregion native)

  5. *ritical-path readiness* smoke tests em todos consumers

    passam

Gate fails → layer fica shadow, incumbent permanece. Não force flip.

Costs / risks

Risk 1 — engenharia massiva

Implementar 6 layers sobre TiKV é trabalho de anos. Time pequeno.

*itigação*

  • Adoção incremental (RFC001 do kdbnext já é essa direção)
  • Reuso de tech upstream (TiKV é battle-tested)
  • Algumas layers (kdbvec, kdbstream) podem ser deferred 2-3 anos
  • Spec aceita usar terceiros temporariamente quando layer ainda

    não existe (Milvus pra vector enquanto kdb-vec não rola)

Risk 2 — vendor lock-in técnico

Stack Koder fica fortemente acoplada a TiKV. Se TiKV (PingCAP) sair do business, Koder herda manutenção do upstream.

*itigação*

  • TiKV é Apache 2.0 license (não vendor-lock estrito)
  • TiKV é CNCF Graduated (community-managed)
  • Apesar disso, alternativas pro substrate (FoundationDB, etc.)

    ficam documented em policies/self-hosted-first.kmd como fallback option.

Risk 3 — performance ceiling local

Substrate distribuído > engine local em algumas cargas (Redis inprocess). Forçar tudo em kdbnext degrada hot paths.

*itigação*

  • §Non-goals lista as 3 categorias que ficam fora
  • Promotion gate #2 exige bench parity antes de flip

Risk 4 — operational complexity migration

Cada migration de layer requer dados-shadow + cutover + rollback plan. 6 migrations × 50 componentes = matrix big.

*itigação*

  • RFC001 do kdbnext já provou o padrão (shadow + diff + flip)
  • Migration tooling reusable (incus snapshots, mig-runners) já

    existe na stack

  • Faseamento conservador (1 layer por trimestre)

Open questions

  1. *kdb-vec` vs Milvus dedicated* ANN em scale > 100M vectors

    é genuinamente domínio especializado. Vale construir kdb-vec ou preservar Milvus como exception permanente igual kdrive?

  1. *ctiveactive conflict resolution* LWW (lastwrite-wins)

    per-key é suficiente, ou precisamos CRDTs serializáveis pra alguns dados (ex: contadores)?

  1. *onsumer migration tax* cada componente flip de Postgres →

    kdbnext, Redis → kdbkv, Timescale → kdb-ts custa horas de refactor. Faseamento detalhado percomponente exige subRFCs.

  1. *ackup story* cross-model snapshot consistente é trivial

    no TiKV (single MVCC timestamp). Mas restore pra um pontono tempo cross-cluster precisa coordination — RFC dedicada provavelmente.

  1. *uthn/authz unified* hoje cada storage tier tem seu auth.

    Kdb-next deveria delegar pra Koder ID nativamente? Quanto acoplamento?

Decision

*tatus: draft*até owner ratificar. Após ratificação:

  • Vira referência canonical pra qualquer decisão de storage na Stack
  • IAs e engs novos consultam-no antes de propor "vamos botar Redis

    pra isso"

  • SubRFCs detalham cada layer (kdbkv, kdbts, kdbvec, kdb-search,

    kdb-stream) — abertas conforme prioridade

  • Roadmap entra em meta/docs/stack/registries/storage-convergence.md

    pra tracking de migration debt per-componente

  • infra/data/kdb/docs/rfcs/kdb-RFC-001 — substrate architecture
  • infra/data/kdb/docs/rfcs/kdb-RFC-007 — time-series storage
  • infra/data/kdb/docs/rfcs/kdb-RFC-008 — multi-region
  • infra/data/kdb/docs/rfcs/kdb-RFC-009 — active-active
  • infra/data/kdb/docs/rfcs/kdb-RFC-011 — read replicas
  • policies/multi-tenant-by-default.kmd — tenant isolation
  • policies/hyperscale-first.kmd — implementation principle
  • policies/self-hosted-first.kmd — promotion gate framework

Significance

Sem RFC, cada novo módulo da Stack escolhe storage isoladamente, acumulando débito técnico de divergência. Em 5 anos seriam 20+ storage tiers diferentes, multiplicando custo operacional e inviabilizando ACID cross-module.

Com RFC, a direção está pinada e qualquer escolha contrária precisa de justificativa explícita (e exception path em §Non-goals).

Esta é a equivalente da "always RDBMS" decision tomada por gigantes nos anos 2000 — exceto que hoje a apostamos é "always TiKV substrate" e ganhamos hyperscale + multi-model nativo.

Source: ../home/koder/dev/koder/meta/docs/stack/rfcs/stack-RFC-001-kdb-as-unified-data-plane.kmd