Documentation

gRPC API

Native HTTP/2 + Protobuf on port 9090 — no external gRPC library. Three services cover unary SQL execution, streaming large result sets, and bidirectional live query subscriptions.

Overview

Absolute DB ships a fully native gRPC server with zero external dependencies — no grpc-c, no libgrpc. The HTTP/2 framing, HPACK header compression, stream multiplexing, flow control, and Protobuf varint encoding are all implemented in pure C11.

PropertyValue
Default port9090
ProtocolHTTP/2 + Protobuf binary
TLSNative TLS 1.3 (no OpenSSL)
PQC hybridX25519 + ML-KEM-768 key exchange
ServicesExecute (unary), Query (server-streaming), Subscribe (bidirectional)
PrometheusRemote write/read at 9090/prom
Compatible clientsgrpc-go, grpc-python, grpcurl, any standard gRPC stub

HTTP/2 stream multiplexing means hundreds of concurrent gRPC calls share a single TCP connection with no head-of-line blocking. HPACK dynamic table compression keeps header overhead minimal even for high-frequency short queries.

Connecting

Start the server with gRPC enabled (it is on by default). The server listens on port 9090 for plaintext or TLS, depending on whether a certificate is configured.

bash — Start server
# Plaintext gRPC (development only)
./bin/absdb-server --port 5433 --grpc-port 9090

# TLS gRPC (recommended for production)
./bin/absdb-server \
  --grpc-port 9090 \
  --tls-cert /etc/absdb/server.crt \
  --tls-key  /etc/absdb/server.key

# Verify gRPC is reachable (plaintext)
grpcurl -plaintext localhost:9090 list

The gRPC server advertises ALPN h2 so that TLS-aware load balancers and proxies (Envoy, nginx) can route correctly. When using mutual TLS, provide --tls-ca to require client certificates.

Services Summary

ServiceRPC PatternUse Case
AbsoluteDB.ExecuteUnarySingle SQL statement — INSERT, UPDATE, DELETE, DDL, or small SELECT
AbsoluteDB.QueryServer-streamingLarge SELECT result sets — rows streamed in batches as they are produced
AbsoluteDB.SubscribeBidirectional streamingLive change stream — receive row-level change events in real time

AbsoluteDB.Execute — Unary RPC

Execute sends a single SQL statement and receives a single response. It is the fastest path for writes and small reads. The response includes the row count affected, column metadata, and up to the first result page of rows.

proto — Execute request / response
message ExecuteRequest {
  string sql        = 1;   // SQL statement to execute
  string database   = 2;   // Target database (optional, uses default)
  repeated Value params = 3; // Positional bind parameters ($1, $2, ...)
  bool   read_only  = 4;   // Hint: refuse writes on read-only replica
}

message ExecuteResponse {
  int64              rows_affected = 1;
  repeated ColumnMeta columns      = 2;
  repeated Row        rows         = 3;
  string              error        = 4; // Empty on success
}

Bind parameters use positional placeholders ($1, $2, ...) matching the PostgreSQL convention. This prevents SQL injection and allows the server to cache the query plan.

AbsoluteDB.Query — Server-Streaming RPC

Query is designed for large result sets. The server streams QueryResponse messages in batches as rows are produced by the executor — the client does not wait for the full result before processing begins. Each batch contains up to 1,000 rows by default (configurable via batch_size).

proto — Query request / streaming response
message QueryRequest {
  string sql        = 1;
  string database   = 2;
  repeated Value params = 3;
  int32  batch_size = 4;   // Rows per response message (default 1000)
  int64  timeout_ms = 5;   // Query timeout in milliseconds
}

// Streamed — server sends N of these per query
message QueryResponse {
  bool               is_first = 1;  // First message contains column metadata
  repeated ColumnMeta columns = 2;
  repeated Row        rows    = 3;
  bool               is_last  = 4;  // Final message (may have 0 rows)
  int64              total_rows = 5; // Set only in last message
}

HTTP/2 flow control prevents the server from overwhelming a slow consumer. The server respects stream window sizes and pauses sending when the client's window is exhausted.

AbsoluteDB.Subscribe — Bidirectional Streaming RPC

Subscribe opens a persistent bidirectional stream for live change events. The client sends subscription commands; the server pushes row-level change events (INSERT, UPDATE, DELETE) as they occur. This is built on the same WAL-tap CDC engine that feeds Debezium-compatible output.

proto — Subscribe messages
// Client sends to open/close subscriptions
message SubscribeRequest {
  enum Action { SUBSCRIBE = 0; UNSUBSCRIBE = 1; ACK = 2; }
  Action action    = 1;
  string table     = 2;   // Table to subscribe to
  string where     = 3;   // Optional server-side filter predicate
  int64  start_lsn = 4;   // Resume from LSN (0 = current)
  int64  ack_lsn   = 5;   // Acknowledge processed up to this LSN
}

// Server sends for each row change event
message ChangeEvent {
  enum Op { INSERT = 0; UPDATE = 1; DELETE = 2; }
  Op     op         = 1;
  string table      = 2;
  int64  lsn        = 3;
  int64  ts_us      = 4;  // Microseconds since epoch
  Row    before     = 5;  // Old row values (UPDATE/DELETE)
  Row    after      = 6;  // New row values (INSERT/UPDATE)
}

Clients send ACK messages to advance the server-side cursor. If the client disconnects, it can resume from its last acknowledged LSN using start_lsn. The server maintains a 100 MB ring buffer to absorb consumer lag.

Proto Definitions

The complete .proto file is shipped with the Absolute DB distribution at clients/proto/absolutedb.proto. You can generate stubs for any language supported by the standard protoc compiler.

bash — Generate stubs
# Python stubs
python -m grpc_tools.protoc \
  -I clients/proto \
  --python_out=. \
  --grpc_python_out=. \
  clients/proto/absolutedb.proto

# Go stubs
protoc \
  -I clients/proto \
  --go_out=. \
  --go-grpc_out=. \
  clients/proto/absolutedb.proto

# List services via reflection (no proto file needed)
grpcurl -plaintext localhost:9090 list AbsoluteDB

Absolute DB also supports gRPC server reflection, so tools like grpcurl and Postman can discover services and methods without the .proto file.

TLS & Authentication

TLS 1.3 on the gRPC port is handled by Absolute DB's native TLS implementation — no OpenSSL or external library is involved. The server advertises ALPN h2 so that HTTP/2 is negotiated during the TLS handshake.

For authentication, pass credentials as gRPC metadata headers:

MethodMetadata KeyValue
PasswordauthorizationBasic base64(user:password)
JWT / OIDCauthorizationBearer <jwt_token>
mTLSClient certificate in TLS handshake
SPIFFE/SVIDX.509 SVID as client cert
bash — TLS with grpcurl
# Using server certificate (TLS, no client cert)
grpcurl \
  -cacert /etc/absdb/ca.crt \
  -H 'authorization: Basic YWRtaW46c2VjcmV0' \
  localhost:9090 \
  AbsoluteDB/Execute

# Mutual TLS
grpcurl \
  -cacert /etc/absdb/ca.crt \
  -cert   /etc/absdb/client.crt \
  -key    /etc/absdb/client.key \
  localhost:9090 \
  AbsoluteDB/Execute

Python Client Example

python — grpc-python unary execute
import grpc
import absolutedb_pb2 as pb
import absolutedb_pb2_grpc as pbg

# Plaintext (development)
channel = grpc.insecure_channel('localhost:9090')

# TLS (production)
# creds = grpc.ssl_channel_credentials(open('ca.crt','rb').read())
# channel = grpc.secure_channel('db.example.com:9090', creds)

stub = pbg.AbsoluteDBStub(channel)

# Unary execute
resp = stub.Execute(pb.ExecuteRequest(
    sql      = 'SELECT id, name FROM users WHERE id = $1',
    params   = [pb.Value(int_val=42)],
    database = 'myapp',
))

for row in resp.rows:
    print(row.values)

# Server-streaming query
req = pb.QueryRequest(
    sql        = 'SELECT * FROM events ORDER BY ts DESC',
    batch_size = 500,
)
for batch in stub.Query(req):
    for row in batch.rows:
        print(row.values)

Go Client Example

go — grpc-go unary execute
package main

import (
    "context"
    "log"

    pb  "github.com/supportcall/absdb-go/proto"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
)

func main() {
    conn, err := grpc.Dial(
        "localhost:9090",
        grpc.WithTransportCredentials(insecure.NewCredentials()),
    )
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    client := pb.NewAbsoluteDBClient(conn)

    // Unary execute
    resp, err := client.Execute(context.Background(), &pb.ExecuteRequest{
        Sql:      "INSERT INTO orders (user_id, total) VALUES ($1, $2)",
        Params:   []*pb.Value{{IntVal: 7}, {FloatVal: 99.95}},
        Database: "myapp",
    })
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("rows affected: %d", resp.RowsAffected)
}

grpcurl Examples

bash — grpcurl one-liners
# List all services
grpcurl -plaintext localhost:9090 list

# Describe Execute method
grpcurl -plaintext localhost:9090 describe AbsoluteDB.Execute

# Run a query (JSON → Protobuf conversion)
grpcurl -plaintext \
  -d '{"sql": "SELECT version()", "database": "myapp"}' \
  localhost:9090 AbsoluteDB/Execute

# Subscribe to a table (streaming — Ctrl+C to stop)
grpcurl -plaintext \
  -d '{"action": 0, "table": "orders"}' \
  localhost:9090 AbsoluteDB/Subscribe

# Resume from a known LSN
grpcurl -plaintext \
  -d '{"action": 0, "table": "orders", "start_lsn": 1048576}' \
  localhost:9090 AbsoluteDB/Subscribe

Prometheus Remote Write / Read

The gRPC port doubles as a Prometheus remote write and remote read endpoint at /prom. This makes Absolute DB a drop-in replacement for Thanos, Cortex, or VictoriaMetrics as a Prometheus long-term storage backend.

yaml — prometheus.yml remote_write configuration
remote_write:
  - url: http://localhost:9090/prom/api/v1/write
    # For TLS:
    # url: https://db.example.com:9090/prom/api/v1/write
    # tls_config:
    #   ca_file: /etc/absdb/ca.crt

remote_read:
  - url: http://localhost:9090/prom/api/v1/read
    read_recent: true

Metrics are stored in the Absolute DB time-series engine (hypertables) and are queryable via standard PromQL as well as SQL. This allows joining application metrics with business data in a single query.

sql — Query Prometheus metrics via SQL
-- All metrics for a specific job in the last hour
SELECT time_bucket('1 minute', ts) AS minute,
       avg(value) AS avg_value
FROM prom_metrics
WHERE name = 'http_requests_total'
  AND labels->>'job' = 'absdb-server'
  AND ts > now() - INTERVAL '1 hour'
GROUP BY minute
ORDER BY minute;

Error Codes

Absolute DB maps internal errors to standard gRPC status codes:

gRPC StatusCodeCause
OK0Success
INVALID_ARGUMENT3SQL parse error, invalid parameter type
NOT_FOUND5Table or database does not exist
ALREADY_EXISTS6Unique constraint violation
PERMISSION_DENIED7Insufficient role privileges
RESOURCE_EXHAUSTED8Connection limit, buffer pool full
FAILED_PRECONDITION9Transaction conflict, serialisation failure
ABORTED10Transaction rolled back
DEADLINE_EXCEEDED4Query timeout exceeded
INTERNAL13Unexpected server error — check server log
UNAVAILABLE14Server shutting down or Raft leader not elected

Detailed error messages are included in the Status.message field and also written to the server log at ERROR level. Enable --log-level debug for full query traces.

Continue Reading

REST API GraphQL API PostgreSQL Wire Protocol

Ready to run Absolute DB?

~154 KB binary  ·  zero external dependencies  ·  2,737 tests passing  ·  SQL:2023 100%

Download Free → View Pricing All Docs