Integration Guide

Protect your databases in under 5 minutes. At runtime, with the transparent TCP proxy or the runtime API, which evaluate each query before it reaches the database. Before anything runs, with the vericto CLI in pre-commit and CI/CD, the validation API, or your AI agent over MCP. Zero credentials stored.

Prerequisites

  • A Vericto account (sign up free)
  • An API key (create one in Dashboard → API Keys)
  • For TCP proxy (runtime protection): Docker or any container runtime to deploy the proxy in your infrastructure
  • For the CLI (pre-commit & CI/CD): a shell, or a CI runner with Node/Docker
  • For the validation API or the runtime API: the ability to make HTTP requests from your pipeline or application
  • For MCP (AI agents): a coding agent that supports remote MCP servers over HTTP, such as Claude Code

Vericto offers five integration modes. Pick by environment; they combine with each other:

ModeWhen to useEnforcement
TCP proxyRuntime: every query your app (or an LLM agent) sends to Postgres/MySQLBlocks in real time, before the query reaches the DB
Runtime APIRuntime over HTTP: your application sends each query before running it, in all four dialectsYour application runs the query only if the answer is not BLOCKED
CLI (vericto)Shift-left: pre-commit hooks and CI/CD, all four dialectsFails the build; SQL is analyzed, never executed
Validation APIPre-execution checks over REST: send batches of SQL from your own tools, without installing the CLIReturns a verdict you act on
MCPWhile writing: your coding agent checks the SQL it generates, before the commit, in all four dialectsThe agent gets the verdict with the line and a suggested fix, and corrects it before proposing the change

Zero credentials: Vericto never stores your database credentials. The TCP proxy runs in your infrastructure and forwards authentication transparently. Your credentials never leave your network.

Step 1: Create workspace & database

  1. Go to /register and create your account
  2. Navigate to Dashboard → Databases → Add Database
  3. Enter a name (e.g. prod-users-db) and select the dialect. PostgreSQL and MySQL can run through the transparent TCP proxy; Oracle, SQL Server and Snowflake are evaluated via the HTTP API, the CLI and MCP only (Snowflake has no TCP wire protocol, so there is no proxy).
  4. Copy the Database ID. You'll need it for configuration
  5. Go to Dashboard → API Keys and create a key with the rules:read and telemetry:write scopes (the only ones the proxy needs: it pulls its ruleset and reports telemetry). The proxy evaluates SQL locally, so it does not need the AST evaluation scope. Copy it securely.

That's all you need from the Vericto dashboard. No connection strings, no credentials.

TCP Proxy: Production database protection

The TCP proxy intercepts every SQL query at the wire protocol level, for both PostgreSQL and MySQL (choose with VERICTO_WIRE_PROTOCOL). Deploy it as a sidecar or standalone container in your infrastructure. Your app connects to the proxy with the same credentials it uses for the database directly.

# docker-compose.yml
services:
  vericto-proxy:
    image: ghcr.io/vericto/vericto-proxy:latest
    ports:
      - "5433:5433"
    environment:
      VERICTO_API_URL: "https://api.vericto.com"
      VERICTO_API_KEY: "${VERICTO_API_KEY}"
      VERICTO_DATABASE_ID: "${VERICTO_DATABASE_ID}"
      VERICTO_WIRE_PROTOCOL: "postgres"   # or "mysql"
      UPSTREAM_HOST: "your-db-host.rds.amazonaws.com"
      UPSTREAM_PORT: "5432"
      PROXY_LISTEN_PORT: "5433"
      # Remote DB (RDS): encrypt the proxy → database hop.
      UPSTREAM_SSLMODE: "require"   # or "verify-full" + UPSTREAM_SSLROOTCERT

  app:
    environment:
      # Point your app to the proxy — same user:pass as before
      DATABASE_URL: "postgres://user:pass@vericto-proxy:5433/mydb"
    depends_on:
      - vericto-proxy

Configuration reference

All proxy configuration is passed via environment variables. Only UPSTREAM_HOST is required; the control-plane link turns on as soon as you set VERICTO_API_URL and VERICTO_API_KEY. Omit them and the proxy still evaluates with its built-in default ruleset (handy for dev or air-gapped setups).

VariableDefaultDescription
Upstream (proxy → database)
UPSTREAM_HOSTrequiredYour database host. The only strictly required variable.
UPSTREAM_PORT5432 / 3306Database port. The default depends on the protocol (Postgres 5432, MySQL 3306).
VERICTO_WIRE_PROTOCOLpostgrespostgres or mysql. Selects the protocol parser and the default ports.
PROXY_LISTEN_PORT5433 / 3307Port the proxy listens on for your app. Default by protocol (Postgres 5433, MySQL 3307).
Control plane (proxy → Vericto API)
VERICTO_API_URL—Vericto API URL. Use https://api.vericto.com. Setting it (with the key) enables telemetry and rule sync.
VERICTO_API_KEY—Workspace API key (vtro_…) with rules:read + telemetry:write scopes. Store it as a secret.
VERICTO_DATABASE_ID—The Database ID this proxy protects. Tags telemetry and selects that database's rules. Without it, the proxy does not report telemetry.
VERICTO_RULES_SYNC_INTERVAL_SECS300How often the proxy polls for ruleset changes. Minimum 30 s (lower values are clamped to 30).
Evaluation and health
VERICTO_MAX_QUERY_BYTES10485760Largest query the proxy will evaluate (10 MiB). Anything above is refused without being analysed, with rule code VERICTO-QUERY-TOO-LARGE. Raise it if your legitimate workloads (batch inserts, long IN lists) run past the limit; the real ceiling is the wire protocol's (64 MiB on Postgres, 16 MiB on MySQL). In monitor mode the query is forwarded unevaluated instead of refused.
VERICTO_HEALTHZ_PORT—Dedicated TCP port for load-balancer health checks. Answers without touching the database, and does not accept connections until the proxy has finished warming up. Omitted means the port is not opened.
TLS (see the next section)
UPSTREAM_SSLMODEdisabledisable, require, or verify-full. Encrypts the proxy → database hop.
UPSTREAM_SSLROOTCERT—CA for verify-full. If omitted, uses the system public CA roots.
UPSTREAM_SSLCERT / UPSTREAM_SSLKEY—Client certificate for upstream mTLS (cert auth). Applies only on the PostgreSQL hop.
PROXY_TLS_MODEdisabledisable or require. Terminates TLS on the app → proxy hop.
PROXY_TLS_CERT / PROXY_TLS_KEY—Server certificate and key (PEM) when PROXY_TLS_MODE=require.
Telemetry (see the next section)
VERICTO_TELEMETRY_BUFFERmemorymemory or disk. Buffering strategy before delivery.
VERICTO_TELEMETRY_DISK_PATH/var/lib/vericto/spoolSpool directory when the buffer is disk.
VERICTO_TELEMETRY_MEMORY_CAPACITY10000Max events in the in-memory ring buffer before the oldest are dropped.
VERICTO_TELEMETRY_BATCH_SIZE100Max events sent in each POST /ingest/events batch.
VERICTO_TELEMETRY_FLUSH_SECS5How many seconds between reporter flushes of the buffer to the API.

Encrypting connections (TLS)

Proxy → database. When your database is remote (e.g. a managed RDS/Cloud SQL instance), encrypt the proxy → database hop with UPSTREAM_SSLMODE. The proxy performs the PostgreSQL SSLRequest negotiation and tunnels the session through TLS:

# Encryption only (does not verify the server certificate)
UPSTREAM_SSLMODE=require

# Encryption + verify the certificate chain and hostname
UPSTREAM_SSLMODE=verify-full
UPSTREAM_SSLROOTCERT=/etc/vericto/rds-ca.pem   # omit to use public CA roots

# Optional: mutual TLS — present a client cert so the proxy authenticates to a
# database configured with `cert` auth (one service identity for the proxy)
UPSTREAM_SSLCERT=/etc/vericto/proxy-client.crt
UPSTREAM_SSLKEY=/etc/vericto/proxy-client.key

Client → proxy. By default the proxy declines client TLS, because it is meant to run inside the same trusted boundary as your app (sidecar, same host, or private subnet) where that hop never leaves your network. To encrypt it natively, set PROXY_TLS_MODE=require with a server certificate and key. The proxy answers the SSLRequest with 'S' and terminates TLS as the server:

PROXY_TLS_MODE=require
PROXY_TLS_CERT=/etc/vericto/server.crt
PROXY_TLS_KEY=/etc/vericto/server.key

Vericto recommends terminating client TLS at the proxy when:

  • The app → proxy hop crosses an untrusted network (different host, VPC, or AZ) instead of a sidecar / private subnet.
  • Your driver enforces sslmode=require and you don't want to run a TLS-terminating load balancer (AWS NLB, HAProxy) in front.
  • A compliance baseline mandates encryption in transit on every hop.

If the proxy already runs as a sidecar or in the same private subnet, leave it disabled. It isn't needed. This is server-side TLS (the client authenticates the proxy); the proxy relays auth end-to-end, so scram-sha-256, md5 and cloud token auth (IAM / Entra) work unchanged. SCRAM channel binding (SCRAM-SHA-256-PLUS) and per-end-client cert auth are not supported through a TLS-terminating proxy by design. Both exist to detect a proxy in the middle. Inspecting SQL requires decrypting at the proxy, so opaque end-to-end TLS is incompatible with enforcement.

Telemetry buffering: memory vs. disk

The proxy buffers evaluation events before sending them to the Vericto API. Two strategies are available:

ModeBehaviorBest for
memory (default) Events are held in a fixed-size ring buffer (default: 10,000 events). If the API is unreachable, the oldest events are dropped when the buffer fills. They are lost on container restart. Low-latency environments where losing some events during API outages is acceptable. Zero disk I/O overhead.
disk Events are written to an append-only spool on disk. It survives container restarts and prolonged API outages. The reporter reads from and removes from the spool after a successful delivery. Compliance-critical environments (SOC2, ISO 27001) where no event may be lost. Requires mounting a persistent volume.

Configuration via environment variables:

VERICTO_TELEMETRY_BUFFER=memory|disk        # default: memory
VERICTO_TELEMETRY_DISK_PATH=/var/lib/vericto/spool
VERICTO_TELEMETRY_MEMORY_CAPACITY=10000

Important: telemetry is always non-blocking. Regardless of the buffer mode, the SQL evaluation path is never delayed by telemetry I/O. Events are sent to the buffer asynchronously after the decision is made.

Resource recommendations

The proxy is designed to be lightweight. The AST engine compiles to native code and evaluates queries in-process, with no network calls on the critical path.

WorkloadCPUMemoryDiskQueries/sec
Small (dev, staging) 0.25 vCPU 64 MB None (memory buffer) Up to 1,000 q/s
Medium (production) 0.5 vCPU 128 MB 100 MB (if disk buffer) Up to 10,000 q/s
High (high throughput) 1 vCPU 256 MB 500 MB (disk buffer) 50,000+ q/s

Key factors: CPU scales with query complexity (queries with multiple JOINs require parsing more AST nodes). Memory scales with the number of connections (each TCP session holds ~4 KB of state). Disk is only needed for telemetry buffering in disk mode.

Latency target: P99 < 2ms for rule evaluation. The proxy adds negligible overhead compared to the network round-trip to your database.

Frameworks & ORMs

Once the proxy is running, point your app to it. The only change is the host, same credentials, same database name:

ORM / DriverConfigurationExample
Prisma DATABASE_URL in .env postgres://user:pass@vericto-proxy:5433/mydb
SQLAlchemy create_engine(url) postgresql+psycopg2://user:pass@proxy:5433/mydb
Drizzle ORM connectionString postgres://user:pass@proxy:5433/mydb
TypeORM host + port in DataSource host: 'vericto-proxy', port: 5433
ActiveRecord DATABASE_URL postgres://user:pass@proxy:5433/mydb
Go (pgx/lib-pq) sql.Open("postgres", url) postgres://user:pass@proxy:5433/mydb
Java (JDBC) jdbc:postgresql://host:port/db jdbc:postgresql://vericto-proxy:5433/mydb
.NET (Npgsql) Host=;Port=;Database= Host=vericto-proxy;Port=5433;Database=mydb

Runtime API: evaluate each query before running it

It is the TCP proxy, over HTTP. Your application sends each query, one per call, to POST /api/v1/proxy/query right before running it, with the database it targets, and runs it only if Vericto lets it through. Use it for Oracle and SQL Server, which have no TCP proxy, or when you cannot change the connection string. The evaluation is recorded in Queries and the Audit Trail with the HTTP source, and counts toward your monthly queries.

Authenticate with an API key that has the Runtime API scope (proxy:evaluate). The workspace comes from the key, so you only send the query, the database_id (in Dashboard → Databases) and the dialect:

curl -X POST https://api.vericto.com/api/v1/proxy/query \
  -H "Authorization: Bearer $VERICTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query": "DELETE FROM users", "database_id": "<database-id>", "dialect": "oracle"}'

# 403 → {"decision": "BLOCKED", "rule_code": "VERICTO-001", "severity": "critical", ...}

Act on the status code:

  • 200: run the query. decision is ALLOWED, FLAGGED or MONITORED; the last two are marked in the dashboard.
  • 403: do not run it. decision is BLOCKED, with rule_code, severity and, when there is one, suggested_safe_query. It is also the answer when the engine is unavailable: the API fails closed.
  • 429: the plan's monthly query quota is used up (Free and Builder only: Team and Enterprise never get a 429 for volume), or the key went over its per-minute safety limit (100 per second by default). Decide what to do then: the safe choice is not to run it (fail closed). The X-Quota-Remaining header on every response warns you before you get there.
  • 400: the SQL could not be parsed in that dialect.

Sensitive columns. When the database has sensitive columns with the mask policy, the 200 response can carry rewritten_query: run that query instead of the original, and the masked columns come back already masked. sensitive_columns lists the tagged columns the query reads. The Runtime API cannot enforce it: an application that runs the original reads the real values. Only the TCP proxy enforces masking.

Want to check a whole migration file without running it? That is the validation API: batches of up to 500 queries, nothing runs.

CLI: shift-left in pre-commit & CI/CD

The vericto CLI validates SQL against your workspace's rules before it ever runs, in pre-commit hooks and CI pipelines. It's a thin client: it sends SQL to your workspace (POST /api/v1/ci/check-key) and mirrors the verdict as a process exit code. SQL is analyzed, never executed. Works with all four dialects (PostgreSQL, MySQL, Oracle, SQL Server) and is available on every plan, metered by a monthly checks allowance where each statement analyzed counts as one.

TCP proxy vs. CLI: the proxy protects runtime traffic (queries your app or an LLM agent actually sends). The CLI protects authoring time (migrations and SQL in code review), so unsafe queries never merge. Most teams use both.

Install & authenticate

# Shell installer (Linux / macOS)
curl -fsSL https://github.com/vericto/vericto-cli/releases/latest/download/vericto-cli-installer.sh | sh

Authenticate once. On a laptop, vericto login opens your browser and mints a scoped 30-day key. Nothing is pasted. In CI, provide an API key via the VERICTO_API_KEY environment variable (or use OIDC, below):

vericto login                 # browser login (developer at a keyboard)
vericto doctor                # verify config, connectivity, auth & plan quota

# Check migrations locally — exit 1 if anything is blocked
VERICTO_API_KEY=vtro_... vericto check migrations/*.sql --dialect postgres

CI/CD pipelines

The CLI is a thin client that mirrors the verdict as a process exit code, so it works in any CI that can run a command. vericto init scaffolds a ready-to-commit template for GitHub Actions and GitLab CI; on CircleCI, Jenkins, and others you wire it by hand (same command, gated on the exit code). --changed checks only the *.sql files changed against the merge base, so PRs stay fast:

# GitHub Actions — .github/workflows/vericto.yml
name: Vericto SQL Check
on: pull_request
permissions:
  contents: read
  security-events: write   # required to upload SARIF to the Security tab
jobs:
  sql-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }   # --changed needs history for the merge base
      - run: npm install -g @vericto/vericto-cli
      - run: vericto check --changed --format sarif --output vericto.sarif
        env:
          VERICTO_API_KEY: ${{ secrets.VERICTO_API_KEY }}
      - uses: github/codeql-action/upload-sarif@v4   # inline PR annotations
        if: always()   # upload findings even when the check step exits non-zero
        with:
          sarif_file: vericto.sarif

Exit codes let CI tell a real block from an outage: 0 clean · 1 a finding at/above --fail-on (default block) · 2 usage error · 3 auth/config error · 4 backend/network error. Use --monitor to report findings but always exit 0 during initial rollout.

Keyless CI auth (OIDC): instead of storing a static vtro_... key, a pipeline can authenticate with a short-lived per-run token via OIDC / workload identity, the same federation GitHub Actions and GitLab CI already provide. Create a trust policy for the workspace in the dashboard, then run vericto check --changed --oidc --workspace ws_123. The key is held in memory only, never written to disk.

Pre-commit hook & baseline

Catch unsafe SQL before it's even committed. vericto init --hook installs the hook; adopting the CLI on a repo with pre-existing SQL won't turn the build red on day one. Record a baseline so only new findings fail:

vericto init --hook                                  # install the pre-commit hook

# Baseline existing findings, then fail only on new ones
vericto baseline migrations/*.sql                    # writes .vericto-baseline.json
vericto check migrations/*.sql --baseline .vericto-baseline.json

Suppress a single finding inline. A reason is required, so it stays accountable:

DELETE FROM users; -- vericto:ignore[VERICTO-001] one-off backfill, tracked in JIRA-42

Validation API: check batches of SQL without running them

Prefer to call Vericto from your own tooling instead of the CLI? Evaluate SQL over REST at POST /api/v1/ci/check-key, authenticated with an API key (scope ci_dryrun:execute). Queries are analyzed but never executed. This is the same endpoint the CLI uses. Reach for it only when the CLI doesn't fit your workflow.

Unlike the runtime API, here you send a batch (all the queries of a migration file, say), nothing runs and no registered database is needed. It uses the checks allowance, shared with the CLI and MCP: one check per statement. If the batch needs more checks than are left, it is rejected whole with 429 QUOTA_EXCEEDED, with nothing evaluated, and the response carries remaining (what is left) and requested (what the batch needed).

Send a batch of up to 500 queries, each tagged with its source line. The response returns a per-query verdict and an exit_code (1 if anything was blocked):

Code examples

# curl — evaluate one or more queries
curl -s -X POST https://api.vericto.com/api/v1/ci/check-key \
  -H "X-API-Key: $VERICTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "dialect": "postgres",
    "file_name": "0001_init.sql",
    "queries": [
      { "line": 1, "sql": "ALTER TABLE users DROP COLUMN email;" }
    ]
  }'

# Response:
# {
#   "summary": { "total": 1, "blocked": 1, "allowed": 0, "ruleset_version": "…" },
#   "queries": [
#     { "line": 1, "status": "BLOCKED", "rule_code": "VERICTO-014",
#       "severity": "high", "ast_node_path": "…", "suggested_fix": "…" }
#   ],
#   "exit_code": 1
# }

For most pipelines the vericto CLI is simpler. It handles batching, --changed detection, baselines, and SARIF/Code-Quality output for you.

MCP: check SQL from your AI agent

Connect your coding agent to Vericto's remote MCP server (https://mcp.vericto.com/mcp) and check every migration or query against your workspace rules while the agent writes it. It uses the same API key (scope ci_dryrun:execute) and the same monthly quota as the CLI.

With the key exported as VERICTO_API_KEY, connect Claude Code with one command. The single quotes keep the key out of the saved configuration:

claude mcp add --scope user --transport http vericto https://mcp.vericto.com/mcp \
  --header 'Authorization: Bearer ${VERICTO_API_KEY}'

From then on, the agent calls check_sql with the whole file and gets a verdict per statement, with its line. Each statement costs one check, the same as through the CLI.

Other clients, the six tools, quota and troubleshooting: AI agents (MCP).

Verify & monitor

Once integrated, verify the setup is working:

  • TCP Proxy: Go to Dashboard → Databases and click "Verify connection". The proxy will report its status within seconds.
  • CLI: Run vericto doctor to confirm config, connectivity, auth, and your remaining monthly quota in one command.
  • Runtime API: send DELETE FROM users: it should answer 403 with VERICTO-001 and show up in Queries with the HTTP source.
  • Validation API: send a test batch and check the response. A 200 with "exit_code": 0 and "status": "ALLOWED" confirms the integration works.
  • MCP: in Claude Code, /mcp should list vericto as connected with 6 tools. Ask the agent to check DELETE FROM users: the answer should be BLOCKED with VERICTO-001.
  • Dashboard: Navigate to the Queries page to see real-time evaluation events flowing in, and the SQL checks page for the history of checks from the CLI, the API and agents (MCP).

Enable Observe Mode during initial rollout. It logs all decisions without blocking anything, so you can validate your ruleset before enforcing it.