prest
Health Pass
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Community trust — 4557 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
PostgreSQL ➕ REST, low-code, simplify and accelerate development, ⚡ instant, realtime, high-performance on any Postgres application, existing or new
pRESTd
pREST (PostgreSQL REST), is a simple production-ready API, that delivers an instant, realtime, and high-performance application on top of your existing or new Postgres database.
PostgreSQL version 9.5 or higher
Contributor License Agreement -
Problems we solve
The pREST project is the API that addresses the need for fast and efficient solution in building RESTful APIs on PostgreSQL databases. It simplifies API development by offering:
- A lightweight server with easy configuration;
- Direct SQL queries with templating in customizable URLs;
- Optimizations for high performance;
- Enhanced developer productivity;
- Authentication and authorization features;
- Pluggable custom routes and middlewares.
Overall, pREST simplifies the process of creating secure and performant RESTful APIs on top of your new or old PostgreSQL database.
Why we built pREST
When we built pREST, we originally intended to contribute and build with the PostgREST project, although it took a lot of work as the project is in Haskell. At the time, we did not have anything similar or intended to keep working with that tech stack. We've been building production-ready Go applications for a long time, so building a similar project with Golang as its core was natural.
Additionally, as Go has taken a huge role in many other vital projects such as Kubernetes and Docker, and we've been able to use the pREST project in many different companies with success over the years, it has shown to be an excellent decision.
1-Click Deploy
Heroku
Deploy to Heroku and instantly get a realtime RESTFul API backed by Heroku Postgres:
Documentation
Visit https://docs.prestd.com/
MCP over HTTP
pREST can expose a read-only MCP-style HTTP endpoint at /_mcp on the same server that already serves catalog, CRUD, and script routes.
This route is intended to reuse the existing pREST request pipeline rather than introduce a separate process or transport. That means the MCP surface inherits the same deployment model, auth, ACL, and database routing behavior already used by the rest of the API.
Endpoint shape
GET /_mcpreturns a discovery payload with server metadata and available tools.POST /_mcpaccepts JSON-RPC style requests for MCP operations.
Currently supported methods:
initializetools/listtools/call
Read-only tools
The first implementation is intentionally read-only. It exposes generic discovery tools and schema-aware table tools:
prest.list_databasesprest.list_schemasprest.list_tablesprest.describe_tableprest.select_tableprest.select.{database}.{schema}.{table}
The schema-aware prest.select.{database}.{schema}.{table} tools are generated from the catalog and give MCP clients a stable, explicit read path for known tables.
Generated table tools now include typed input schemas derived from table metadata. MCP clients can inspect these schemas to discover:
- allowed
columns - allowed
order_byfields (fieldand-fieldfor descending) - column-aware
filters limitandoffset
In multi-database mode, tool generation expands across registered aliases.
Example initialize request:
POST /_mcp
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize"
}
Example tool call:
POST /_mcp
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "prest.describe_table",
"arguments": {
"database": "prest-test",
"schema": "public",
"table": "test"
}
}
}
Example schema-aware table tool call with projection, filter, and ordering:
POST /_mcp
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "prest.select.prest-test.public.test",
"arguments": {
"columns": ["id", "name"],
"filters": {
"name": "prest tester"
},
"order_by": ["id"],
"limit": 5,
"offset": 0
}
}
}
Safety model
- The MCP endpoint is read-only by design in the current version.
- Unsupported tools return
400 Bad Request. - Existing pREST database routing and identifier validation still apply.
- Auth and ACL stay in the HTTP stack instead of being reimplemented in the MCP layer.
- When auth is enabled,
/_mcprequires authentication like other protected routes.
Tests
The MCP route is covered by unit and integration tests, including live HTTP checks under integration/controllers/mcp_test.go and route coverage in integration/router/routes_test.go.
Multi-database
pREST uses the first URL path segment as the database selector for CRUD, catalog, and optional script routes. Two modes are supported:
| Mode | When | {database} in URL |
Connection target |
|---|---|---|---|
| Legacy multi-DB | No registry configured | Postgres database name | Same pg.host; dbname = path segment |
| Registry multi-cluster | [[databases]] or env registry set |
Registered alias | Per-profile host, port, and credentials |
URL routing
All table operations use /{database}/{schema}/{table}:
GET /tenant-a/public/users
POST /tenant-a/public/orders
GET /tenant-a/public
GET /_QUERIES/tenant-a/myqueries/get_all
Script routes accept an optional database prefix (/_QUERIES/{database}/{queriesLocation}/{script}). When omitted, the default database (pg.database) is used.
Request flow: validate alias → set connection context → open or reuse pool for that alias → execute query.
Configuration
Registry sources are merged in priority order: indexed env pairs → TOML (env wins on conflict).
Environment variables (production / Kubernetes)
Register databases with contiguous 1-based index pairs:
DATABASE_ALIAS_1=tenant-a
DATABASE_URL_1=postgres://user:[email protected]:5432/app_a?sslmode=require
DATABASE_ALIAS_2=tenant-b
DATABASE_URL_2=postgres://user:[email protected]:5432/app_b?sslmode=require
PREST_DATABASE_ALIAS_N and PREST_DATABASE_URL_N are accepted as aliases of the above keys.
See install-manifests/kubernetes/deployment.yaml for a multi-secret example with liveness/readiness probes.
TOML (local development)
pg.* remains the default/fallback profile; registry entries override host, port, and credentials per alias:
[pg]
database = "prest-test"
single = false
[[databases]]
alias = "prest-test"
host = "postgres"
port = 5432
database = "prest-test"
user = "postgres"
pass = "postgres"
ssl.mode = "disable"
[[databases]]
alias = "secondary-db"
host = "postgres-b"
port = 5432
database = "secondary-cluster"
user = "postgres"
pass = "postgres"
ssl.mode = "disable"
When no registry is configured, legacy DATABASE_URL / pg.* behavior is unchanged.
Alias vs physical database name
- URLs and access rules use the alias (e.g.
tenant-a). - Connection pools use the profile's
database,host, and credentials (e.g.app_aoncluster-a.example.com). - When alias equals the physical database name (legacy mode), behavior matches pre-registry pREST.
pg.single
Set pg.single = false to allow routing to multiple databases or aliases. When true and a registry is active, only the default database alias is accepted.
Connection pooling
Pools are keyed by connection URI; aliases that share the same URI share a pool. Connections are opened lazily on first request per alias.
Connection budgeting: plan for replicas × aliases × pg.maxopenconn connections per cluster. Use PgBouncer or RDS Proxy when many aliases are registered.
Health checks
| Endpoint | Purpose | Behavior |
|---|---|---|
GET /_health |
Liveness | Pings the default database |
GET /_ready |
Readiness | Pings the default database and every registered alias |
Access control
access.tables entries support an optional database field for per-alias permissions:
[[access.tables]]
database = "tenant-a"
schema = "public"
name = "users"
permissions = ["read"]
Local testing
Multi-cluster integration tests live in integration/controllers/multicluster_test.go. They require a second Postgres service (PREST_PG_HOST_B) provided by docker-compose-test.yml:
make test-integration
Testing
Run unit tests locally:
make test-unit
Run the full integration suite inside Docker (Postgres, deployed prestd servers, no local setup required):
make test-integration
Or directly with Docker Compose:
docker compose -f docker-compose-test.yml up -d --wait postgres postgres-b db-init prestd prestd-multicluster prestd-auth
docker compose -f docker-compose-test.yml run --rm --no-deps tests
docker compose -f docker-compose-test.yml down -v --remove-orphans
Compose starts postgres, postgres-b, a one-shot db-init job (testdata/db-init.sh), three prestd services (prestd, prestd-multicluster, prestd-auth), then runs go test ./integration/... in the tests container. Standard HTTP integration tests call those servers via PREST_TEST_URL, PREST_MULTICLUSTER_TEST_URL, and PREST_AUTH_TEST_URL.
Running go test ./integration/... outside compose skips network tests when those URLs are unset.
Example: Docker Build
You can build the Docker image locally for development (this compiles the code from source):
docker build -t prest/prest:latest .
For release builds, GoReleaser uses the same Dockerfile / Dockerfile.noplugins with a pre-built prestd binary (no go.mod in the build context). Local source builds pass version metadata via build arguments:
docker build \
--build-arg VERSION=v1.0.0 \
--build-arg COMMIT=hash \
--build-arg DATE=2026-02-11 \
-t prest/prest:latest .
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found
