CockroachDB — API Surface#

API types#

CockroachDB exposes five distinct API surfaces:

  1. PostgreSQL wire protocol — the primary user-facing SQL interface
  2. gRPC/DRPC internal API — inter-node KV, Raft, gossip, and cluster management (not for end users)
  3. HTTP REST API — two tiers: a REST v2 API (/api/v2/) and a grpc-gateway bridge (/_admin/v1/, /_status/)
  4. CLI — the cockroach binary, used for operations, administration, and debugging
  5. 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
    • COPY protocol (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: PreServeConnHandler dispatches 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/pgerror defining 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)#

ServiceKey RPCsPurpose
InternalBatch, BatchStream, RangeLookup, MuxRangeFeed, GossipSubscription, ResetQuorum, TokenBucket, Join, GetSpanConfigs, UpdateSpanConfigs, TenantSettings, GetRangeDescriptorsAll-in-one service for system-tenant inter-node communication
KVBatchBatch, BatchStreamDRPC-only subset of Internal for the hot batch path
NodeJoinNew node joining the cluster
RangeFeedMuxRangeFeedStreaming key range change events (CDC, schema change)
TenantServiceTenantSettings, GossipSubscription, RangeLookup, GetRangeDescriptorsSystem tenant → secondary tenant communication
TenantUsageTokenBucketPer-tenant resource accounting (token bucket for serverless)
TenantSpanConfigGetSpanConfigs, GetAllSystemSpanConfigsThatApply, UpdateSpanConfigs, SpanConfigConformanceTenant span configuration management
QuorumRecoveryResetQuorumEmergency quorum recovery

Storage-level services (pkg/kv/kvserver/storage_services.proto)#

ServiceKey RPCsPurpose
MultiRaftRaftMessageBatch, RaftSnapshot, DelegateRaftSnapshotRaft log replication and snapshot transfer between replicas
PerReplicaCollectChecksum, WaitForApplication, WaitForReplicaInitPer-replica administrative operations
PerStoreCompactEngineSpan, GetTableMetrics, ScanStorageInternalKeys, SetCompactionConcurrencyPer-store (Pebble) engine operations

Infrastructure services#

ServiceProto fileKey RPCs
Gossippkg/gossip/gossip.protoGossip (bidirectional stream) — cluster membership and config propagation
Heartbeatpkg/rpc/heartbeat.protoPing — clock offset measurement + connection liveness
SideTransportpkg/kv/kvserver/closedts/ctpb/service.protoPushUpdates — closed timestamp propagation for follower reads
Tracingpkg/util/tracing/tracingservicepb/tracing_service.protoGetSpanRecordings — distributed trace collection

Admin/Management services (pkg/server/serverpb/)#

ServiceKey RPCs
AdminUsers, Databases, DatabaseDetails, TableDetails, TableStats, Events, SetUIData, GetUIData, Cluster, Settings, Health, Liveness, Jobs, Drain, Decommission, DecommissionStatus, RangeLog, DataDistribution, EnqueueRange, SendKVBatch, ListTracingSnapshots, RecoveryCollectReplicaInfo, RecoveryStagePlan, RecoveryVerify, ListTenants
StatusCertificates, 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 / LogOutUserLogin, UserLogout — session cookie authentication
InitBootstrap — cluster initialization
MigrationValidateTargetClusterVersion, BumpClusterVersion, SyncAllEngines, PurgeOutdatedReplicas, WaitForSpanConfigSubscription — rolling upgrade coordination
TimeSeriesQuery, 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:

  1. kvAuth.unaryInterceptor — calls authenticateAndSelectAuthzRule() to select the authorization policy (cluster auth via TLS cert, or tenant auth via tenant capabilities)
  2. Metrics interceptor — records request counts and latency per RPC method
  3. Recovery interceptorgatewayRequestRecoveryInterceptor catches panics on gateway-bridged requests
  4. 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/

EndpointHandlerAuthNotes
login/authServer.ServeHTTPNoObtain session token
logout/authServer.ServeHTTPNoInvalidate session
sessions/listSessionsViewClusterMetadataActive SQL sessions
nodes/listNodesViewClusterMetadataCluster nodes list
nodes/{node_id}/ranges/listNodeRangesViewClusterMetadataRanges on a node
ranges/hot/listHotRangesViewClusterMetadataHot range statistics
ranges/{range_id}/listRangeViewClusterMetadataSingle range details
health/healthNoNode health check
health/restart_safety/restartSafetyCheckNoSafe to restart?
users/listUsersRegularList database users
events/listEventsViewClusterMetadataCluster event log
databases/listDatabasesRegularList databases
databases/{name}/databaseDetailsRegularDatabase details
databases/{name}/grants/databaseGrantsRegularDB privilege grants
databases/{name}/tables/databaseTablesRegularTables in database
databases/{name}/tables/{table}/tableDetailsRegularTable details
sql/execSQLRegularExecute SQL statement
database_metadata/GetDbMetadataRegularDB metadata (tenant-enabled)
database_metadata/{id}/GetDbMetadataWithDetailsRegularDB metadata with details
table_metadata/GetTableMetadataRegularTable metadata
table_metadata/{id}/GetTableMetadataWithDetailsRegularTable metadata details
table_metadata/updatejob/TableMetadataJobRegularTrigger metadata refresh
grants/databases/{id}/getDatabaseGrantsRegularGrants by DB ID
grants/tables/{id}/getTableGrantsRegularGrants by table ID
rules/listRulesRegularPrometheus alerting rules
dbconsole/nodes/dbconsole.GetNodesViewClusterMetadataDB Console node info

Middleware chain for v2 endpoints:

  1. callCountDecorator — telemetry counter increment (all routes)
  2. authMux (outer mux) — redirects unauthenticated requests for auth-required routes to 401
  3. authserver.NewRoleAuthzMux — role-based authorization check (for non-RegularRole routes)
  4. 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 /health
  • GET /databases — list databases
  • GET /databases/{database}/tables/{table} — table details
  • GET /events — cluster event log
  • GET /settings — cluster settings
  • GET /jobs — background job status
  • POST /drain — streaming drain request
  • POST /decommission/{node_id} — node decommission
  • GET /rangelog — Raft range log

Status API (accessible at /_status/):

  • GET /_status/vars — Prometheus metrics (/metrics also works)
  • GET /_status/nodes — node list
  • GET /_status/sessions — active SQL sessions
  • GET /_status/statements — statement statistics
  • GET /_status/hotranges — hot range statistics
  • GET /_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 string

Flag patterns#

  • Global persistent flags: --certs-dir, --insecure, --host, --port, --user, --url (connection flags, defined in pkg/cli/cliflagcfg)
  • Environment variable fallback: All flags can be overridden via COCKROACH_* env vars through pkg/util/envutil.EnvOrDefaultXxx() and cliflagcfg.ProcessEnvVarDefaults()
  • Server flags: --listen-addr, --advertise-addr, --join, --store, --cache, --max-sql-memory, --locality, --background
  • TLS flags: --certs-dir, --ca-key for cert subcommands; --insecure to 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:

RPCPurpose
ListPods(ListPodsRequest)List running SQL pods for a tenant
WatchPods(WatchPodsRequest) → streamStream pod lifecycle events
EnsurePod(EnsurePodRequest)Start a SQL pod if none running (scale-to-zero)
GetTenant(GetTenantRequest)Get tenant metadata
WatchTenants(WatchTenantsRequest) → streamStream tenant lifecycle events

The proxy itself is started via cockroach mt start-sql-proxy (defined in pkg/cli/mt_proxy.go). It:

  1. Accepts incoming PostgreSQL connections on a forwarding port
  2. Reads the SNI (TLS server name) or connection string to identify the target tenant
  3. Calls EnsurePod() on the directory server to wake a tenant SQL pod if needed
  4. 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.