23
Design Philosophy

PostgREST Design Philosophy

Embed Size (px)

Citation preview

Page 1: PostgREST Design Philosophy

Design Philosophy

Page 2: PostgREST Design Philosophy

goal: Schema → API

Can we use the declarative information in a

relational db schema to mechanically generate

an HTTP API?

Page 3: PostgREST Design Philosophy

Tables/views → Routes

Always one level deep

Page 4: PostgREST Design Philosophy

WHERE clause → query params

Just simple operators like less, greater,

equality, inequality

Provide more complicated logic as views

Page 5: PostgREST Design Philosophy

Primary key → eq: param(s)

A primary key identifies at most a single row

They can be compound and/or natural

Routes like /foo/1 don’t always suffice

/foo?k1=eq.v1&k2=eq.v2

Page 6: PostgREST Design Philosophy

For instance,

if an employee belongs to a dept

Link: <http://me.com/dept?id=eq:7>; rel="dept"

Foreign keys → header links

Page 7: PostgREST Design Philosophy

Limit, offset → Range headers

HTTP/1.1 206 Partial Content

Accept-Ranges: items

Content-Range: 0-24/100

Range-Unit: items

RFC7233

GET /items HTTP/1.1

Range-Unit: items

Range: 0-24

Page 8: PostgREST Design Philosophy

SQL update → HTTP patch

PATCH /people?age=lt.12

{ "type": "child" }

Updates all the matching ones

Page 9: PostgREST Design Philosophy

SQL insert → HTTP post

POST /items

Page 10: PostgREST Design Philosophy

PUT /items?pk=eq.val

with all fields specified in body

SQL upsert → HTTP put

Page 11: PostgREST Design Philosophy

schema search path → API Version

Use numerical schema names in the db

Set schema search path to mask endpoints and

fall through when desired

GET /foo HTTP/1.1

Accept: application/vnd.me.com+format; version=n

Page 12: PostgREST Design Philosophy

DB Roles → OAuth

Web server authenticates you

then connects as your user to db

DB authorizes your (hence server) actions

Page 13: PostgREST Design Philosophy

Column constraints → OPTIONS

We can pipe the options output into a client

side “Faker” to mock server responses for the

client test suite.

Page 14: PostgREST Design Philosophy

PG stats collector → cache headers

The access and modification patterns in a table

can provide a heuristic for http caching headers

Perhaps a special view could allow overriding

etags, max-age, etc for each table via a sql

expression

Page 15: PostgREST Design Philosophy

EXPLAIN → HTTP 413

The server can examine the query plan and

preemptively forbid inefficient requests

Like large seq scans or nested join loops

Page 16: PostgREST Design Philosophy

Deployment is easy

For instance on Heroku create a buildpack that

installs the server binary

Then push new migrations and run them. The

only way to update your api server is through

migrations.

Page 17: PostgREST Design Philosophy

Use robust migration tool

github.com / theory / squitch

• Follows a git-inspired workflow

• Models dependencies as a graph, not a line

• TDD at the SQL level!

• No conflicts between branches with git union merge strategy (unlike schema.rb)

Page 18: PostgREST Design Philosophy

Efficiency!

This can be much

faster than Rails

Page 19: PostgREST Design Philosophy

Efficiency! Use a fast language.

The web server itself doesn’t change so we

don’t need the convenience of a scripting

language.

Compile it once for your platform.

Page 20: PostgREST Design Philosophy

I’m using the Warp server on Haskell

Page 21: PostgREST Design Philosophy

Removing imperative cruft

Processing that happens in Ruby models is

glacially slow compared with tuned C inside

postgres.

Page 22: PostgREST Design Philosophy

Generate JSON inside Postgres

Dockyard measured that Postgres’ internal

JSON generation was 2X/10X faster than

ActiveRecord Serializers for small data and

160X faster for large data.

Page 23: PostgREST Design Philosophy

github.com/begriffs/postgrest

github.com/begriffs/postgrest-heroku

github.com/begriffs/postgrest-example