All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
v0.2.0 — 2026-08-23
Added
db_prepared_statements(PostgRESTdb-prepared-statements,PGRST_DB_PREPARED_STATEMENTS, defaulttrue): the hot-path statements — the auth preamble, reads, mutations, and RPC — are cached as named prepared statements on each pool connection, skipping the parse step when a query shape repeats. Set it tofalsebehind a transaction-mode pooler such as PgBouncer (#127).
Changed
- Typed filter values and RPC scalar arguments are now bound as parameters
(
($n::text)::<type>) instead of being inlined as escaped literals ('<v>'::<type>). The server-side coercion — and every error it can raise — is identical (PostgreSQL I/O-conversion casts), the conformance suite is byte-for-byte unchanged, and it matches the SQL PostgREST executes ("id" = $1). This is what makes the statement cache effective: requests differing only in their values now share one SQL text (#127).
Fixed
- PGRST205/PGRST202 not-found errors (and their "Perhaps you meant" hints)
now qualify the missing table/function with the request's active schema,
matching real PostgREST (
Error.hsbuildsqi <> "." <> namefrom the resolved profile). Previously area-mirror schemas were reported astest.<name>— an assumption the conformance suite's oracle disproved. Conformancespec/bumped tov16.0.0-suite.3, which pins the corrected behavior (cases 1360/1368/1373).
v0.1.0 — 2026-08-18
First release. Bier serves a RESTful API generated at boot from PostgreSQL introspection, reproducing the request/response behavior of PostgREST v16.0.
The API surface
- Reads with the full PostgREST query grammar:
select(columns, aliases, casts, JSON paths, computed columns, aggregates), horizontal filters and the operator set, logical trees (and/or, negation, nesting), quantifiers, ordering,limit/offsetandRangepagination, and resource embedding (many-to-one, one-to-many, many-to-many,!inner, spread, aliases, disambiguation). - Mutations —
POSTinsert,PATCHupdate,PUTsingle-row upsert,DELETE— withPrefer: return=,resolution=,missing=default,handling=strictandmax-affected=. /rpc/<function>calls overGET/HEAD/POST, rendering every routine return kind (scalar, composite,SETOF,TABLE(...),void).- Every request compiled into a single parameterized SQL statement whose response bodies are byte-identical to PostgREST's, row separators and embedded-JSON internals included.
- Content negotiation across
application/json,text/csv,application/geo+json(relations, mutations, RPC and embedded reads, wherever PostGIS is installed), thevnd.pgrst.object/arrayvariants withnulls=stripped, andvnd.pgrst.plan. Prefer: timezone=<tz>for per-requesttimestamptzrendering, including numeric UTC offsets.- A generated OpenAPI document at the root, with per-role privilege
filtering, an opt-in OpenAPI 3.0.3 emitter (
openapi_version: "3.0", a Bier extension), anddb_root_specto replace it wholesale.
Authentication
- JWT verification through JOSE: HS256/384/512, plus RS/ES/PS/EdDSA from a
JWK or JWK Set, with the algorithm family decided by the key's shape rather
than the token's
algheader. - Role switching and request-scoped GUCs (
request.jwt.claims, headers, cookies,app.settings.*), applied as a single batchedSELECT set_config(…)statement per request — one database round trip for the whole preamble, the same shape PostgREST executes. jwt_role_claim_keyas an RFC 9535 JSON Path into the claims,jwt_secret_is_base64,jwt_aud, and a per-instance verification cache.db_pre_request, run inside the request transaction before the main query.
Operations
- Multiple named instances per BEAM node, each with its own configuration, connection pool, runtime-built router, and Bandit server.
- Schema-cache reload over
LISTEN/NOTIFYandBier.reload_schema_cache/1; a failed reload leaves the previous snapshot serving. - Standalone operation with no host application: PostgREST-compatible
PGRST_*environment variables, a config-file parser, the in-database (ALTER ROLE … SET pgrst.*) configuration source, abierescript with--dump-config/--example, amix releasetarget, and a Dockerfile. - Observability:
:telemetryevents for requests, schema-cache loads, pool status, JWT cache and SSE; an Apache-combined access log gated bylog_level, with optionallog_query;Server-Timing; a trace-header passthrough; and/live+/readyon an optional admin listener. - Query cancellation at the PostgreSQL backend when the HTTP client
disconnects (
cancel_on_disconnect, on by default) — something PostgREST cannot do.
Beyond PostgREST
- Realtime events: a config-gated SSE endpoint bridging Postgres
LISTEN/NOTIFYto browsers (events_channels,events_path,events_heartbeat_interval). PostgREST has no equivalent. Vary: Originon CORS responses that echo the request'sOrigin, which upstream omits.- RFC 4180 CSV quoting, where upstream emits malformed CSV for values containing quotes or newlines.
Server: bier/<version>and an OpenAPIinfo.versionreporting Bier's own version. The PostgREST dialect is advertised through the document'sexternalDocsinstead.
The README's "Deliberate divergences from PostgREST" section is the authoritative list; everything else is intended to match upstream byte for byte.