Id RFC 001 architecture overview
RFC-001 — Architecture Overview
- *tatus:*Draft
- *ate:*2026
0408 - *uthor:*Koder Team
Summary
Koder ID is a cloudnative Identity and Access Management (IAM) platform built from scratch in Go, following a microservices architecture. It provides OIDC/OAuth2 authentication and authorization with multitenancy, WebAuthn/Passkeys support, and uses KDB as its storage backend.
Goals
- *ull control*— every line of code is ours, no third-party IAM runtime dependency
- *calability*— each service scales independently, inspired by Ory's architecture
- *ecurity*— Argon2id hashing, hybrid sessions, WebAuthn, TOTP
- *ogfooding*— validate KDB as a production database through real-world usage
- *ulti-tenancy*— tenant isolation from day one
Non-Goals (MVP)
- SAML protocol support (future RFC)
- LDAP connector (future RFC)
- Admin UI (API + CLI only in MVP)
- Social login / external IdP federation (future RFC)
Architecture
Microservices
The system is composed of 5 domain services, plus an API Gateway and a CLI tool (7 binaries total):
┌─────────────────────────────────────────────────────────────────┐
│ External Clients │
│ (Browser, Mobile Apps, Koder Products) │
└──────────────────────────┬──────────────────────────────────────┘
│ HTTPS (REST)
▼
┌─────────────────────────────────────────────────────────────────┐
│ API Gateway │
│ (rate limiting, routing) │
└───┬──────────┬──────────┬──────────┬──────────┬─────────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐┌────────┐┌────────┐┌────────┐┌────────┐
│Identity││ Auth ││ OAuth2 ││Session ││ Admin │
│Service ││Service ││ /OIDC ││Service ││Service │
│ ││ ││Service ││ ││ │
└───┬────┘└───┬────┘└───┬────┘└───┬────┘└───┬────┘
│ gRPC │ gRPC │ gRPC │ gRPC │
└────┬────┘────┬────┘────┬────┘────┬────┘
│ │ │ │
▼ ▼ ▼ ▼
┌─────────────────────────────────────┐
│ KDB │
│ (database per service) │
└─────────────────────────────────────┘Service Responsibilities
| Service | Responsibility | Port (default) |
|---|---|---|
| *dentity* | User CRUD, profile, credentials storage, password hashing (Argon2id) | 4001 |
| *uth* | Authentication flows: email+password, TOTP, WebAuthn/Passkeys verification | 4002 |
| *Auth2/OIDC* | Authorization server: authorization code flow, token issuance, JWKS, discovery | 4003 |
| *ession* | Session lifecycle: create, validate, refresh, revoke. Hybrid JWT + stateful | 4004 |
| *dmin* | Tenant management, client registration, API key management, system configuration | 4005 |
Communication
- *nter-service:*gRPC over HTTP/2 with Protocol Buffers
- Strongly typed contracts via
.protofiles - Mutual TLS (mTLS) between services in production
- Service discovery via DNS (Kubernetes) or static config (standalone)
- Strongly typed contracts via
- *xternal clients:*REST/HTTP over HTTPS
- OpenAPI 3.1 specification
- OIDC endpoints follow the spec exactly (no custom paths)
- JSON request/response bodies
Data Isolation
Each microservice owns its own KDB namespace (logical database):
| Service | KDB Namespace |
|---|---|
| Identity | koder_id_identity |
| Auth | koder_id_auth |
| OAuth2/OIDC | koder_id_oauth |
| Session | koder_id_session |
| Admin | koder_id_admin |
Services *ever*access another service's namespace directly — always via gRPC.
Multi-Tenancy
Every entity in every namespace includes a tenant_id field. Tenant resolution:
- *omain-based:*
acme.id.koder.dev→ tenantacme - *eader
based:*`XTenant-ID: acme` (for API clients) - *oken-based:*extracted from JWT claims (for authenticated requests)
Row-level security in KDB enforces tenant isolation at the database layer.
Deployment
Each service is a standalone Go binary:
koder-id-identity
koder-id-auth
koder-id-oauth
koder-id-session
koder-id-admin
koder-id-cli # CLI tool that talks to Admin service
koder-id-gateway # API Gateway / reverse proxyDeployment options:
- *ingle host:*all binaries on one machine, different ports
- *ontainers:*one container per service (Docker/Podman)
- *ubernetes:*one deployment per service with HPA
Directory Structure
platform/id/v2/
├── proto/ # Protocol Buffer definitions
│ ├── identity/v1/
│ ├── auth/v1/
│ ├── oauth/v1/
│ ├── session/v1/
│ └── admin/v1/
├── services/
│ ├── identity/ # Identity service
│ │ ├── cmd/ # main.go
│ │ ├── internal/
│ │ │ ├── handler/ # gRPC + REST handlers
│ │ │ ├── service/ # Business logic
│ │ │ ├── repository/ # KDB access layer
│ │ │ └── model/ # Domain models
│ │ └── go.mod
│ ├── auth/ # Auth service
│ │ └── (same structure)
│ ├── oauth/ # OAuth2/OIDC service
│ │ └── (same structure)
│ ├── session/ # Session service
│ │ └── (same structure)
│ ├── admin/ # Admin service
│ │ └── (same structure)
│ └── gateway/ # API Gateway
│ └── (same structure)
├── cli/ # CLI tool
│ ├── cmd/
│ └── go.mod
├── pkg/ # Shared libraries
│ ├── crypto/ # Argon2id, JWT, JWKS
│ ├── tenant/ # Tenant resolution middleware
│ ├── kdb/ # KDB client wrapper
│ ├── version/ # Build version info
│ └── proto/ # Generated protobuf code
├── docs/
│ ├── rfcs/ # RFCs (this directory)
│ ├── api/ # OpenAPI specs (planned)
│ └── diagrams/ # Architecture diagrams (planned)
├── deploy/
│ ├── docker/ # Dockerfiles
│ ├── migrate/ # Zitadel migration scripts and checklists
│ ├── kubernetes/ # K8s manifests (planned)
│ └── systemd/ # Systemd units
├── tests/
│ ├── integration/ # Cross-service integration tests
│ └── e2e/ # End-to-end tests
└── MakefileSecurity Considerations
- All inter-service communication uses mTLS in production
- Secrets (DB credentials, signing keys) injected via environment variables, never in config files
- JWT signing keys rotated automatically (configurable interval, default 24h)
- Rate limiting at gateway level (configurable per endpoint)
- Audit log for all write operations (who, what, when, from where)
- No plaintext passwords ever logged or stored — only Argon2id hashes
Open Questions
- Should we use an event-sourced model (like current Zitadel) or traditional CRUD?
- API Gateway: custom Go proxy or existing solution (Envoy, Traefik)?
- KDB client library: does it exist for Go, or do we need to build it?