Skip to content

Conversation

@maxweber
Copy link
Owner

@maxweber maxweber commented Dec 15, 2025

One point in Ideas for DataScript 2 is:

UUIDs for entity IDs makes it easier to generate new IDs in distributed environment without consulting central authority.

With this PR dbval would use UUIDs for entity IDs.

The biggest motivator for me is to avoid the need to assign an external ID to each entity. In past we often made the mistake to share Datomic entity IDs with the outside world (via an API for example), while this is strictly discouraged. In Datomic and Datascript each transaction also receive its own entity ID. dbval uses colossal-squuid UUIDs for transaction entity IDs. They increase strictly monotonically, meaning:

A SQUUID generated later will always have a higher value, both lexicographically and in terms of the underlying bits, than one generated earlier.

With com.yetanalytics.squuid/uuid->time you can extract the timestamp that is encoded in the leading bits of the SQUUID:

(uuid->time #uuid "017de28f-5801-8fff-8fff-ffffffffffff")
;; => #inst "2021-12-22T14:33:04.769000000-00:00"

This timestamp can serve as :db/txInstant to capture when the transaction has been transacted. UUIDs for entity and transaction IDs would allow to entirely get rid of tempids. However, they are still supported by dbval for convenience and to assign data to the transaction entity:

(d/transact! conn
  [[:db/add "e1" :name "Alice"]

   ;; attach metadata to the transaction
   [:db/add :db/current-tx :tx/user-id 42]
   [:db/add :db/current-tx :tx/source :api]])

Another compelling option of using UUIDs is that dbval databases become mergeable, if they adhere to the same schema. Thereby you can solve the following challenge: if you have a separate database per customer it is no longer possible to run database queries to get statistics across your customer base. With dbval you can merge all customer databases into a big one to run these statistics queries.

One obvious downside of UUIDs is that they need twice as much storage in comparison to 64 bit integers.

maxweber and others added 3 commits December 15, 2025 10:40
Major changes:
- Entity IDs are now random java.util.UUID instead of sequential integers
- Transaction IDs use time-ordered squuids from com.yetanalytics/squuid
- Legacy tempid formats (negative integers, strings) are auto-converted to UUIDs
- String tempids like {:db/id "e1"} now work and map to UUIDs in :tempids

Key implementation changes in db.cljc:
- Extended find-vector-upserts to detect regular unique identity upserts
  for vector ops (not just tuple attrs)
- Added conflicting upsert detection for vector ops when same tempid
  resolves to different entities
- Added :db/current-tx upsert conflict detection
- Fixed ref tempid handling in find-vector-upserts

Test updates:
- Updated all tests to use string tempids and capture UUIDs from :tempids
- Fixed test isolation issues (fresh db for each assertion)
- Updated error message regex patterns to match new formats
- Fixed entity-map ref extraction (wraps refs in {:db/id uuid})

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove `numeric-eid-exists?` alias
- Remove positive integer handling in `resolve-id` (now throws error)
- Make `entid` throw error for integers instead of returning nil
- Rename `legacy-tempid?` to `tempid?` (negative ints and strings are valid tempids, not legacy)
- Update comments to remove "legacy" terminology
- Fix test to use string tempids instead of positive integers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
maxweber and others added 8 commits December 16, 2025 06:04
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Entity IDs are now UUIDs, not integers. Updated the quick path
optimization in getter-fn and removed the obsolete number? type
guard in entity.cljc.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@maxweber maxweber marked this pull request as ready for review December 20, 2025 18:59
@maxweber maxweber merged commit 5dd525d into main Dec 26, 2025
1 check passed
@maxweber maxweber deleted the uuids branch December 26, 2025 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants