Hacker News new | ask | show | jobs
by DrScientist 1008 days ago
Whether it's method calls or database schema - isn't what really matters is control of what's accessible and the tools you have to support evolution?

So when you provide an API - you don't make all functions in your code available - just carefully selected ones.

If you use the DB schema as a contract you simply do the same - you don't let people access all functions - just the views/tables they need/you can support.

Just like API's, databases have tools to allow you to evolve - for example, maintaining views that keep a contract while changing the underlying schema.

In the end - if your schema dramatically changes - in particular changes like 1:1 relation moving to a 1:many - it's pretty hard to stop that rippling throughout your entire stack - however many layers you have.

2 comments

> Just like API's, databases have tools to allow you to evolve - for example, maintaining views that keep a contract while changing the underlying schema.

What are the database tools for access logs, metrics on throughput, latency, tracing etc.? Not to mention other topics like A/B tests, shadow traffic, authorization, input validation, maintaining invariants across multiple rows or even tables...

Databases often either have no tools for this or they are not quite as good.

- Access logs: audit logging [0]

- Throughput/latency: pg_stat_statements [1] or Prometheus' exporter [2]

- A/B tests: aren't these frontend things? recording which version a user got is an INSERT

- Auth: row-level security [3] and session variables

- Tracing, shadow traffic: I don't think these are relevant in a "ship your database" setup.

- Valdation: check constraints [4] and triggers [5]

Maybe by some measures they're "not quite as good", but on the other hand you get them for free with PostgreSQL. I've lost count of how many bad internal versions of this stuff I've built.

[0]: https://severalnines.com/blog/postgresql-audit-logging-best-...

[1]: https://www.postgresql.org/docs/current/pgstatstatements.htm...

[2]: https://grafana.com/oss/prometheus/exporters/postgres-export...

[3]: https://www.postgresql.org/docs/15/ddl-rowsecurity.html

[4]: https://www.postgresql.org/docs/15/ddl-constraints.html

[5]: https://www.postgresql.org/docs/15/plpgsql-trigger.html

Honestly, there's plenty of tools out there that can do the same thing.

The important crux of the counterpoint to this article is "if you ship your database, it's now the API" and everything that comes along with that.

All the problems you _think_ you're sidestepping by not building an API, you're actually just compounding further down the line when you need to do things to do your database other than simply "adding columns to a table". :\

Edit: re-reading, the point I didn't make is that having your database be your API _is_ viable, so long as you actually treat it as an API instead of an internal data structure.

You can do impedance-matching code in a database, e.g. in stored procedures, but I think the experience is strictly worse than all the application-level tooling that's available.
Not sure what you mean.

Are you just taking about the expected shape of the data - the consumer of the database can do that either in SQL or at some later layer they control.

If you are talking about my 1:1 -> 1:N problem. I'd argue that can ripple all the way though to your UI ( you now need to show a list, where once it was a single value etc ) - not something you can actually fix at the API level per se.

Bottom line, the more layers of indirection, the more opportunities you have to transform - but potentially also the more layers you do have to transform if the change is so big that you can't contain it.

Let's be clear - I'd typically favour APIs -especially if I don't control the other end. But I'm saying it's about the principals of surface area and evolvability, not really whether it's an API or SQL access.