architecture

Drew Verlee 2026-01-08T18:08:35.954389Z

Should conditional logic be handled inside the database or on the server? I think it tends to not matter, but it feels like having them in the database gives much tighter constraints on what states are possible. e.g a user needs a certain role to update a table, that check happening on the server could mean their role is changed between when the server gets the information and when the request up update the tables is made. Basically having the check in the db makes the full request atomic.

Linus Ericsson 2026-01-09T09:03:50.126069Z

There are two different things at play here, one is the implementation of the business logic, the other is handling transaction guarantees in a reasonable way. In Datomic you can write transactor functions, yes, but you can also write a "transaction data generator" on the server that converts everything to datomic primitives (including :db.fn/cas) and possibly some id generating functions as transaction functions. In SQL you can (probably) do the same thing - a "data update statement generator" that also somehow need to guarantee that the state we derived the transaction change from is still intact. This is not to be confused with implementing the business logic in the database statements/database functions. Database functions and the like could still be nescessary to be able to fulfil transaction guarantees.

seancorfield 2026-01-09T15:17:00.170049Z

@drewverlee If you're concerned about race conditions, you can either work with transactions or you can ensure your updates also check the condition, and then check result -- how many rows were updated -- to verify success. It depends on how time-critical such things need to be.

Drew Verlee 2026-01-09T19:07:21.889809Z

thansk @oscarlinusericsson and @seancorfield i'll chew on this.

seancorfield 2026-01-08T18:10:29.294459Z

I'm a big fan of trying to keep the database as purely a persistence mechanism, and therefore have no logic in the db.

👍 2
➕ 5
Drew Verlee 2026-01-08T18:19:46.856409Z

The tables themselves wouldn't have logic (e.g triggers or constraints) but a db function could wrap the intent e.g only admins can delete users.

Drew Verlee 2026-01-08T18:21:36.045869Z

I guess i'm assuming the conditional logic in postgres actually makes a transaction...

Drew Verlee 2026-01-08T18:21:44.519379Z

IF ELSE branchs.

Drew Verlee 2026-01-08T18:23:14.363999Z

It seems like it is according to Gemini (with some slight modifications).

neumann 2026-01-08T23:15:28.778039Z

I've ended up on projects where the database is the integration mechanism. That turned into a lot of stored procedures and constraints. Not fun. I share @seancorfield's opinion.

Drew Verlee 2026-01-09T07:25:33.132979Z

@neumann Sure, but there is difference between a constraint within a DB function/procedure (same thing right?) and one on your server. If i write if user = admin on my server, based off a user session, and by the time they get around to issuing that query, their no longer an admin, because someone removed their privilege, the DB would be able to see that change, but the server would have stale data. Does that matter? Most of the time probable not, but it's different and i feel like the reason I don't consider the DB function route isn't because it's better for the use cases i have in mind, but because i'm less good at writing DB functions and understanding them then working with clojure.

Drew Verlee 2026-01-09T07:27:09.570269Z

One of potential upsides of Datomic was that you could write your DB functions in clojure... of course it's still tricky...

Pavel Filipenco 2026-01-11T21:02:30.375379Z

Since datomic's mechanisms were mentioned, might as well mention Rama, where microbatch topologies give you exclusive access to local data, thus guaranteeing ACID semantics. Maybe you're not going to use it, but hey that's another approach https://redplanetlabs.com/docs/~/acid.html#gsc.tab=0

👍 1
Drew Verlee 2026-01-12T03:44:03.177479Z

thanks @pavel.filipenco