back to projects
public · MITmulti-tenant saas

Kairos

Multi-tenant OKR platform with database-enforced isolation.

github
Tenant leak surface0Enforced by RLS, not app code
Idempotency window24hStripe-style key cache
Audit logPartitionedMonthly, immutable, JSONB diff

The problem

Most OKR tools enforce multi-tenancy in the application layer — one missed WHERE clause and tenant A sees tenant B's strategy. Kairos pushes isolation into the database, so a bug in the API still cannot leak data across workspaces.

Architecture

Next.js 14 frontend
Spring Boot REST API
PostgreSQL with Row Level Security policies per tenant (`SET LOCAL app.current_workspace` set on every JDBC connection via a HikariCP customizer)
Redis-backed Idempotency-Key cache and ZSET sliding-window rate limits
SSE via SseEmitter fanned out across instances by Redis pub/sub
insert-only, monthly-partitioned audit log with before/after JSONB.

Key decisions

DECISIONCHOICEWHY
Tenant isolationPostgres RLS over application-layer filteringA missed WHERE clause cannot leak data when the database enforces isolation. Convention is a bug waiting to happen.
IdempotencyRedis-backed Idempotency-Key header (Stripe pattern)Frontend retries and webhook re-delivery should never double-write. 24h TTL, cached response returned on replay.
Rate limitingRedis ZSET sliding windowPer-workspace throttling without fixed-window cliffs. O(log N) accuracy via ZADD/ZRANGEBYSCORE.
Real-timeSSE over WebSocketsProgress updates are unidirectional; SSE is simpler, load-balancer friendly, and HTTP/2 multiplexes it for free.
Java 21Spring BootNext.jsPostgres RLSRedisSSEDocker