2 min readKolaybase Team

How to Build a REST API on PostgreSQL Without Writing Boilerplate

Stop hand-writing CRUD controllers. Learn how an auto-generated, PostgREST-style REST API turns your PostgreSQL schema into a production endpoint instantly.

REST APIPostgreSQLPostgRESTbackend

Most REST APIs are 80% boilerplate: a controller per table, the same list/create/update/delete handlers, pagination, filtering, and validation copied over and over. PostgreSQL already knows your schema — so why describe it twice?

The boilerplate problem

A typical hand-written endpoint looks like this:

app.get("/articles", async (req, res) => {
  const { status, limit = 20, offset = 0 } = req.query;
  const rows = await db.query(
    "select * from articles where status = $1 limit $2 offset $3",
    [status, limit, offset],
  );
  res.json(rows);
});

Multiply that by every table and every filter combination. It's repetitive, error-prone, and drifts out of sync with the database.

Generate the API from the schema

With Kolaybase, the schema is the API. Define a table and it's immediately available over REST with filtering, ordering, and pagination built in:

# Filter, order, and paginate — all from the query string
GET /articles?status=eq.published&order=created_at.desc&limit=20

The same query through the SDK:

const { data } = await kb
  .from("articles")
  .select("id, title, author:authors(name)")
  .eq("status", "published")
  .order("created_at", { ascending: false })
  .range(0, 19);

Notice author:authors(name) — related tables are embedded in a single request, no N+1 queries and no custom join endpoint.

Filtering operators you get for free

OperatorMeaningExample
eqequalsstatus=eq.published
gtgreater thanviews=gt.1000
likepattern matchtitle=like.*postgres*
inin listid=in.(1,2,3)
isnull checkdeleted_at=is.null

Security still lives in the database

Auto-generated doesn't mean wide open. Row-level security policies decide who sees what, enforced by PostgreSQL itself:

alter table articles enable row level security;

create policy "authors read own drafts"
  on articles for select
  using (auth.uid() = author_id or status = 'published');

The API respects the policy automatically — no permission checks scattered across controllers.

The takeaway

Hand-written CRUD is a maintenance tax. Let PostgreSQL's schema and policies be the single source of truth, and let the REST layer be generated from it. You write product features; the plumbing writes itself.

Read the full REST API reference or see how Kolaybase compares to Supabase.

Keep reading