biff 2026-07-07

Hello, I've got a question. I'm on Biff 1.0, though excited to see whats coming down the pipe for 2.0. I'm trying to setup a schema with a {:db.unique :db.unique/identity} constraint, but I can still insert multiple documents with identical values. I am not finding much information on schema on XTDB's docs, but I assume that has to be a feature. My approach has been declaring a schema in a module, like so:

(def schema 
  {:feed/id :uuid
   :feed [:map {:closed true}
           [:xt/id :feed/id] 
           [:feed/uri {:db/unique :db.unique/identity} :string]
           [(comment "Other properties and so on")]]})

(def module {:schema schema})

Hey! :db.unique/identity isn't actually supported by XTDB. the docs for transactions in v1 are here: https://v1-docs.xtdb.com/language-reference/datalog-transactions/. It's fairly low-level, hence Biff adding its own transaction stuff on top. XT v1 basically has two ways to enforce uniqueness: either by encoding everything you want to be unique inside the :xt/id value, or by using a transaction function (which in turn would just do a regular query to see if there's more than one document with a given attribute value). Biff defines a :biff/ensure-unique transaction function which does the latter; see this page: https://biffweb.com/docs/reference/transactions/

I was beginning to suspect XTDB might not do that... Oh well. Does biff handle 'this key in the schema for :xt/id matches this other part, therefore grab that value instead of generating a UUID?'

I.e. like a datomic lookup ref? no unfortunately, though there are some lookup-* helper functions you can use to query for IDs before submitting a transaction: https://biffweb.com/docs/api/xtdb/

there is also :db.op/upsert (also on https://biffweb.com/docs/reference/transactions/ ) which may or may not do what you need.

Just noting from the tutorial that there was a pattern of declaring, for example :subscription/id at the top level of the schema and then referencing that in the malli type later, and that that could mayhap be leveraged to improve on the id autofilling.

➕ 1

Regardless, thank you for the tool, I'm not certain if I'll stick with it, but Biff has certainly been full of thought provoking ideas. I particularly like the minimal DI setup/module system.

for sure--that's kinda one of my goals for biff, i.e. even if you don't end up using it, it's still a worked example of how you could make a clojure web app, and you can take inspiration from whichever parts seem interesting etc for biff 2 so far I haven't layered anything on top of regular sqlite transactions, other than honeysql, but it could be interesting to explore doing something in that space. e.g. sort of like a write-side version of biff.graph that I just released which gives you more of a graph view over your data instead of a relational view.

However, I can still biff/submit-tx with [{:db/doc-type :feed :feed/uri "" :feed/other-value :foo}] and get multiple entities in my db.