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.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.