Skip to content

Gateway Overview

QQL Gateway

Connect RPC gRPC gRPC-Web

The QQL Gateway is a Connect RPC server (gRPC + gRPC-Web + HTTP/1.1 JSON) that sits in front of Qdrant. It accepts QQL queries over HTTP, enforces policy, executes them, and returns structured responses.

┌──────────┐ Connect RPC ┌───────────┐ gRPC ┌──────────┐
│ Client │ ──────────────────────▶ │ Gateway │ ──────────────▶ │ Qdrant │
│ (any) │ HTTP POST / JSON / gRPC │ (this) │ go-client │ │
└──────────┘ └───────────┘ └──────────┘

Any language can call it — curl, Python, TypeScript, Go, or an LLM agent.

SituationUse
Multi-tenant app — isolate tenant dataGateway with policy + AST injection
Auth-protected Qdrant accessGateway with JWT validation
Multi-language clients (Python + TypeScript + Go)Gateway as unified RPC surface
Audit trail of all queriesGateway with audit logging
Rate-limit per userGateway with token bucket
Agents calling named operationsGateway with query templates
Simple single-service Go appEmbed pkg/qql directly

A plain gateway with no auth or policy is a transparent QQL proxy:

Basic gateway
qql-go serve --qdrant-url http://localhost:6334

Any query passes through. Useful for development or trusted internal networks.

The gateway becomes a policy enforcement point when configured:

FeatureFlag
JWT auth--jwks-url, --jwt-issuer, --jwt-audience
YAML policy--policy-file
Hot-reload policy--policy-reload
Audit logging--audit, --audit-file
Rate limiting--rate-limit, --rate-limit-capacity
Query templates--templates

The gateway doesn't just proxy requests — it parses QQL into an AST and rewrites it before execution.

When a user sends:

QUERY 'company' FROM docs LIMIT 500

The gateway rewrites it to:

QUERY 'company' FROM docs LIMIT 50 WHERE tenant_id = 'acme-corp'
  • Tenant filter comes from the JWT claim — never written by the user
  • LIMIT is capped by policy
  • For CTE-based queries, injection is recursive — every CTE stage gets the filter