CockroachDB — API Surface#
API types#
CockroachDB exposes five distinct API surfaces:
- PostgreSQL wire protocol — the primary user-facing SQL interface
- gRPC/DRPC internal API — inter-node KV, Raft, gossip, and cluster management (not for end users)
- HTTP REST API — two tiers: a REST v2 API (
/api/v2/) and a grpc-gateway bridge (/_admin/v1/,/_status/) - CLI — the
cockroachbinary, used for operations, administration, and debugging - SQL Proxy / Multi-tenant Directory — a CCL gRPC service for CockroachDB Serverless tenant routing
PostgreSQL Wire Protocol (primary user interface)#
- Package:
pkg/sql/pgwire - Port: 26257 by default (configurable via
--listen-addr) - Protocol: Full PostgreSQL wire protocol (v3), including:
- Startup / authentication handshake (MD5, SCRAM-SHA-256, cert-based, GSS)
- Simple and Extended query protocol
COPYprotocol (bulk data ingestion)- PostgreSQL cancellation protocol
- SSL/TLS negotiation
- Entry point:
pgwire.PreServeConnHandler(pre-auth routing) →pgwire.conn.serveImpl()(per-connection goroutine) - Multi-tenant routing:
PreServeConnHandlerdispatches connections to the correct tenant SQL server before authentication, based on SNI (TLS server name) or connection parameters. This is how CockroachDB Serverless routes tenants. - Compatibility: Clients connecting with any PostgreSQL-compatible driver (libpq, JDBC, psycopg2, node-postgres, etc.) connect here.
- Notable: CockroachDB’s PostgreSQL compatibility is not a thin translation layer — the full wire protocol is implemented natively, with
pkg/sql/pgwire/pgerrordefining CockroachDB-specific PostgreSQL error codes for wire-compatible error reporting.
gRPC / DRPC Internal API#
CockroachDB maintains 16+ gRPC services defined across 178 .proto files. These are internal cluster APIs, not intended for end-user consumption.
Transport: dual gRPC + DRPC#
A unique aspect of CockroachDB’s internal API: it uses both gRPC (for external tooling compatibility) and DRPC (a lighter-weight binary RPC protocol developed by Storj) for the hot path:
- gRPC server: Standard Google gRPC, used by the CLI, Admin UI, and grpc-gateway
- DRPC server: Lower overhead for the highest-frequency inter-node KV calls (
Batch,RangeFeed) - Registration pattern: Dual-registration via
gw.RegisterService(grpc.Server)+DRPCRegister*()at server startup (pkg/server/server.go:1349)
Core KV services (pkg/kv/kvpb/api.proto)#
| Service | Key RPCs | Purpose |
|---|---|---|
Internal | Batch, BatchStream, RangeLookup, MuxRangeFeed, GossipSubscription, ResetQuorum, TokenBucket, Join, GetSpanConfigs, UpdateSpanConfigs, TenantSettings, GetRangeDescriptors | All-in-one service for system-tenant inter-node communication |
KVBatch | Batch, BatchStream | DRPC-only subset of Internal for the hot batch path |
Node | Join | New node joining the cluster |
RangeFeed | MuxRangeFeed | Streaming key range change events (CDC, schema change) |
TenantService | TenantSettings, GossipSubscription, RangeLookup, GetRangeDescriptors | System tenant → secondary tenant communication |
TenantUsage | TokenBucket | Per-tenant resource accounting (token bucket for serverless) |
TenantSpanConfig | GetSpanConfigs, GetAllSystemSpanConfigsThatApply, UpdateSpanConfigs, SpanConfigConformance | Tenant span configuration management |
QuorumRecovery | ResetQuorum | Emergency quorum recovery |
Storage-level services (pkg/kv/kvserver/storage_services.proto)#
| Service | Key RPCs | Purpose |
|---|---|---|
MultiRaft | RaftMessageBatch, RaftSnapshot, DelegateRaftSnapshot | Raft log replication and snapshot transfer between replicas |
PerReplica | CollectChecksum, WaitForApplication, WaitForReplicaInit | Per-replica administrative operations |
PerStore | CompactEngineSpan, GetTableMetrics, ScanStorageInternalKeys, SetCompactionConcurrency | Per-store (Pebble) engine operations |
Infrastructure services#
| Service | Proto file | Key RPCs |
|---|---|---|
Gossip | pkg/gossip/gossip.proto | Gossip (bidirectional stream) — cluster membership and config propagation |
Heartbeat | pkg/rpc/heartbeat.proto | Ping — clock offset measurement + connection liveness |
SideTransport | pkg/kv/kvserver/closedts/ctpb/service.proto | PushUpdates — closed timestamp propagation for follower reads |
Tracing | pkg/util/tracing/tracingservicepb/tracing_service.proto | GetSpanRecordings — distributed trace collection |
Admin/Management services (pkg/server/serverpb/)#
| Service | Key RPCs |
|---|---|
Admin | Users, Databases, DatabaseDetails, TableDetails, TableStats, Events, SetUIData, GetUIData, Cluster, Settings, Health, Liveness, Jobs, Drain, Decommission, DecommissionStatus, RangeLog, DataDistribution, EnqueueRange, SendKVBatch, ListTracingSnapshots, RecoveryCollectReplicaInfo, RecoveryStagePlan, RecoveryVerify, ListTenants |
Status | Certificates, Details, Regions, Nodes, NodesList, RaftDebug, Ranges, Gossip, EngineStats, Allocator, ListSessions, CancelQuery, ListContentionEvents, ListDistSQLFlows, SpanStats, Stacks, Profile, Metrics, GetFiles, Logs, ProblemRanges, HotRangesV2, Range, Statements, CombinedStatementStats, StatementDetails, ResetSQLStats, IndexUsageStatistics, TableIndexStats, ListExecutionInsights, NetworkConnectivity |
LogIn / LogOut | UserLogin, UserLogout — session cookie authentication |
Init | Bootstrap — cluster initialization |
Migration | ValidateTargetClusterVersion, BumpClusterVersion, SyncAllEngines, PurgeOutdatedReplicas, WaitForSpanConfigSubscription — rolling upgrade coordination |
TimeSeries | Query, Dump, DumpRaw — internal time series metrics |
gRPC interceptors / middleware#
Authentication and authorization on the gRPC server is handled by kvAuth (pkg/rpc/auth.go), which implements grpc.UnaryServerInterceptor and grpc.StreamServerInterceptor. The interceptor chain:
kvAuth.unaryInterceptor— callsauthenticateAndSelectAuthzRule()to select the authorization policy (cluster auth via TLS cert, or tenant auth via tenant capabilities)- Metrics interceptor — records request counts and latency per RPC method
- Recovery interceptor —
gatewayRequestRecoveryInterceptorcatches panics on gateway-bridged requests - Custom interceptors — registered per server via
rpc.WithInterceptor()for additional path-level checks
For DRPC, equivalent drpcmux.UnaryServerInterceptor and drpcmux.StreamServerInterceptor are chained via drpcmux.NewWithInterceptors().
HTTP REST API#
API v2 (/api/v2/)#
Router: github.com/gorilla/mux (apiV2Server.mux)
Authentication: Session cookie (X-Cockroach-API-Session header). Session obtained via POST /api/v2/login/. Role-based authorization per endpoint.
Base path: /api/v2/
| Endpoint | Handler | Auth | Notes |
|---|---|---|---|
login/ | authServer.ServeHTTP | No | Obtain session token |
logout/ | authServer.ServeHTTP | No | Invalidate session |
sessions/ | listSessions | ViewClusterMetadata | Active SQL sessions |
nodes/ | listNodes | ViewClusterMetadata | Cluster nodes list |
nodes/{node_id}/ranges/ | listNodeRanges | ViewClusterMetadata | Ranges on a node |
ranges/hot/ | listHotRanges | ViewClusterMetadata | Hot range statistics |
ranges/{range_id}/ | listRange | ViewClusterMetadata | Single range details |
health/ | health | No | Node health check |
health/restart_safety/ | restartSafetyCheck | No | Safe to restart? |
users/ | listUsers | Regular | List database users |
events/ | listEvents | ViewClusterMetadata | Cluster event log |
databases/ | listDatabases | Regular | List databases |
databases/{name}/ | databaseDetails | Regular | Database details |
databases/{name}/grants/ | databaseGrants | Regular | DB privilege grants |
databases/{name}/tables/ | databaseTables | Regular | Tables in database |
databases/{name}/tables/{table}/ | tableDetails | Regular | Table details |
sql/ | execSQL | Regular | Execute SQL statement |
database_metadata/ | GetDbMetadata | Regular | DB metadata (tenant-enabled) |
database_metadata/{id}/ | GetDbMetadataWithDetails | Regular | DB metadata with details |
table_metadata/ | GetTableMetadata | Regular | Table metadata |
table_metadata/{id}/ | GetTableMetadataWithDetails | Regular | Table metadata details |
table_metadata/updatejob/ | TableMetadataJob | Regular | Trigger metadata refresh |
grants/databases/{id}/ | getDatabaseGrants | Regular | Grants by DB ID |
grants/tables/{id}/ | getTableGrants | Regular | Grants by table ID |
rules/ | listRules | Regular | Prometheus alerting rules |
dbconsole/nodes/ | dbconsole.GetNodes | ViewClusterMetadata | DB Console node info |
Middleware chain for v2 endpoints:
callCountDecorator— telemetry counter increment (all routes)authMux(outer mux) — redirects unauthenticated requests for auth-required routes to 401authserver.NewRoleAuthzMux— role-based authorization check (for non-RegularRole routes)- Actual handler
grpc-gateway bridge (/_admin/v1/, /_status/)#
CockroachDB uses grpc-gateway to expose its gRPC Admin, Status, LogIn/LogOut, and TimeSeries services as HTTP+JSON endpoints. Route annotation is done in the .proto files using the google.api.http option.
- Base paths:
/_admin/v1/(Admin service),/_status/(Status service) - Content types: JSON (
application/json, default) and Protobuf (application/x-protobuf) - Auth: Translated from HTTP session cookies/headers to gRPC metadata via
authserver.TranslateHTTPAuthInfoToGRPCMetadata - Call count telemetry: gRPC call-count interceptor on the in-process loopback connection (
callCountInterceptor)
Notable Admin API endpoints (accessible at /_admin/v1/):
GET /health— liveness check, also aliased at/healthGET /databases— list databasesGET /databases/{database}/tables/{table}— table detailsGET /events— cluster event logGET /settings— cluster settingsGET /jobs— background job statusPOST /drain— streaming drain requestPOST /decommission/{node_id}— node decommissionGET /rangelog— Raft range log
Status API (accessible at /_status/):
GET /_status/vars— Prometheus metrics (/metricsalso works)GET /_status/nodes— node listGET /_status/sessions— active SQL sessionsGET /_status/statements— statement statisticsGET /_status/hotranges— hot range statisticsGET /_status/logs/{node_id}— log files
CLI#
Framework: github.com/spf13/cobra
Binary: cockroach
Top-level command structure#
cockroach
├── start # Start a node and join/create a cluster
├── start-single-node # Start an insecure single-node cluster
├── init # Bootstrap a new cluster
├── cert # TLS certificate management
│ ├── create-ca # Create cluster CA certificate
│ ├── create-client-ca # Create client CA certificate
│ ├── create-node # Create node TLS certificate
│ ├── create-client # Create client TLS certificate
│ └── list # List certificates
├── sql # Interactive SQL shell
├── statement-diag # Statement diagnostics bundles
│ ├── list # List available bundles
│ ├── download # Download a bundle
│ ├── delete # Delete a bundle
│ └── cancel # Cancel a bundle request
├── auth-session # HTTP session management
│ ├── login # Log in and obtain a session token
│ ├── logout # Invalidate a session
│ └── list # List active sessions
├── node # Node management
│ ├── ls # List cluster nodes
│ ├── status [node_id] # Node health status
│ ├── decommission # Decommission a node
│ ├── recommission # Re-enable a decommissioned node
│ └── drain # Gracefully drain a node
├── node-local # Node-local commands (no cluster connection)
├── userfile # User file storage (uploads to CockroachDB)
├── demo # Launch an in-memory demo cluster
├── convert-url # Convert PostgreSQL connection URL formats
├── gen # Generate artifacts
│ ├── man # Generate man pages
│ ├── autocomplete # Generate shell completions
│ ├── settings-list # List all cluster settings
│ └── metric-list # List all metrics
├── version # Display version info
├── debug # Low-level debugging (expert use)
│ ├── keys # Inspect raw storage keys
│ ├── range-data # Inspect raw range data
│ ├── range-descriptors # Inspect range descriptor table
│ ├── decode-key # Decode an encoded storage key
│ ├── decode-value # Decode an encoded storage value
│ ├── decode-proto # Decode a proto from hex/base64
│ ├── raft-log # Inspect the Raft log for a range
│ ├── estimate-gc # Estimate GC for a range
│ ├── pebble # Direct Pebble database inspection
│ ├── compact # Manually trigger compaction
│ ├── gossip-values # Display gossip values
│ ├── syncbench # Filesystem sync benchmark
│ ├── merge-logs # Merge and filter structured log files
│ ├── intent-count # Count intents in a store
│ ├── doctor # Diagnose cluster metadata corruption
│ │ ├── examine # Examine cluster for issues
│ │ └── recreate # Recreate descriptors from cluster
│ ├── zip # Collect debug data ZIP
│ │ └── upload # Upload a debug ZIP to Cockroach Labs
│ ├── send-kv-batch # Send a raw KV BatchRequest
│ └── declarative-* # Declarative schema changer tools
├── sqlfmt # Format SQL statements
├── workload # Built-in workload generators
│ ├── bank # Simple bank workload
│ ├── kv # KV read/write workload
│ ├── tpcc # TPC-C benchmark
│ ├── tpch # TPC-H benchmark
│ ├── movr # MovR ride-share workload
│ └── ycsb # YCSB workload
└── encode-uri # URI encode a stringFlag patterns#
- Global persistent flags:
--certs-dir,--insecure,--host,--port,--user,--url(connection flags, defined inpkg/cli/cliflagcfg) - Environment variable fallback: All flags can be overridden via
COCKROACH_*env vars throughpkg/util/envutil.EnvOrDefaultXxx()andcliflagcfg.ProcessEnvVarDefaults() - Server flags:
--listen-addr,--advertise-addr,--join,--store,--cache,--max-sql-memory,--locality,--background - TLS flags:
--certs-dir,--ca-keyfor cert subcommands;--insecureto disable TLS for dev clusters
SQL Proxy / Multi-tenant Directory (CCL)#
Package: pkg/ccl/sqlproxyccl
Service: Directory (pkg/ccl/sqlproxyccl/tenant/directory.proto)
CockroachDB Serverless uses a SQL proxy (cockroach mt start-sql-proxy) that intercepts PostgreSQL connections from end users and routes them to the appropriate tenant SQL server. The proxy communicates with a tenant directory server via a dedicated gRPC service:
| RPC | Purpose |
|---|---|
ListPods(ListPodsRequest) | List running SQL pods for a tenant |
WatchPods(WatchPodsRequest) → stream | Stream pod lifecycle events |
EnsurePod(EnsurePodRequest) | Start a SQL pod if none running (scale-to-zero) |
GetTenant(GetTenantRequest) | Get tenant metadata |
WatchTenants(WatchTenantsRequest) → stream | Stream tenant lifecycle events |
The proxy itself is started via cockroach mt start-sql-proxy (defined in pkg/cli/mt_proxy.go). It:
- Accepts incoming PostgreSQL connections on a forwarding port
- Reads the SNI (TLS server name) or connection string to identify the target tenant
- Calls
EnsurePod()on the directory server to wake a tenant SQL pod if needed - Proxies the PostgreSQL wire protocol to the tenant’s SQL pod
Key API Design Observations#
1. grpc-gateway as an HTTP API strategy#
Rather than implementing separate HTTP handlers for every admin operation, CockroachDB annotates its protobuf service definitions with google.api.http options and generates HTTP bindings via grpc-gateway. This means the Admin and Status services are effectively implemented once (in Go, as gRPC servers) and exposed as both gRPC and HTTP+JSON automatically. The v2 REST API (/api/v2/) was added later for endpoints that needed a cleaner JSON interface outside the grpc-gateway model.
2. PostgreSQL protocol as the SQL API contract#
By committing to full PostgreSQL wire protocol compatibility rather than a custom SQL protocol, CockroachDB inherits the entire PostgreSQL client ecosystem. This is an unusual API decision for a new database — most would define a custom protocol — but it eliminates the need for proprietary drivers and makes CockroachDB a drop-in replacement in many PostgreSQL deployments.
3. Internal gRPC API is not versioned for external use#
The internal gRPC services (Internal, Node, MultiRaft, etc.) are not intended as public APIs. There is no versioning strategy for them — they use protobuf for wire compatibility, but the services evolve with cluster version upgrades. The Migration service exists specifically to coordinate rolling upgrades where nodes may be running different versions simultaneously.
4. Dual gRPC + DRPC transport for hot paths#
The decision to support both gRPC and DRPC on the same node reflects a performance optimization: DRPC has lower overhead for the very frequent Batch and BatchStream RPCs (millions per second on a busy cluster). The KVBatch service is defined as the DRPC-specific subset of Internal. This dual-transport pattern required significant infrastructure investment (pkg/rpc/drpc.go), but it decouples the operational tooling from the performance-critical path.
5. Explicit authentication tiers for the HTTP API#
The v2 REST API has a three-tier role model: RegularRole (any authenticated user), ViewClusterMetadataRole (can see cluster topology), and AdminRole (full admin access). This is enforced at the route registration level by authserver.NewRoleAuthzMux, not by individual handlers — making authorization policy visible in one place (registerRoutes()) rather than scattered across handlers.
6. Multi-tenant API routing before authentication#
The PreServeConnHandler dispatches PostgreSQL connections to tenant SQL servers before the authentication handshake. This means tenant isolation is enforced at the network routing layer, not just within a single SQL process. The implication: a compromised tenant cannot attempt to authenticate as another tenant — the connection is already committed to a tenant SQL server before passwords are checked.