Bring immutability to your database.

Data changes. History should not.

Datomic is the free database built on immutable values, designed for a complete audit trail and queries over any past state.

Diagram of tree rings growing outward over time.

Build to remember

Datomic is for systems that can't afford to forget. It shines when provenance, decision tracing, and as-of queries are central design requirements that can’t be retrofit.

Tracing what happened and why

When a workflow reaches an unexpected state, how it got there is your first question. With Datomic root-cause analysis happens in the database, not sifting through logs.

Supply Chain · Logistics

Who knew what, when?

In domains where documentation is evidence, corrections must be additive, not destructive. In Datomic, facts like treatment records, consent forms, and regulatory filings are amended without losing record of the past.

Healthcare · Legal

Flexible data modeling

Datomic adapts to fit your data in whatever shapes make sense, without worry of impedance mismatch.

Many indexes

  • EAVT — “row” lookups: everything known about an entity
  • AEVT — “column” scans: every value for an attribute
  • AVET — k/v and range lookups: find entities by attribute value
  • VAET — hierarchical traversal: walk reference attributes backwards from a value
  • Pull queries express document- and graph-shaped reads over the same indexes

Decoupled scaling

Datomic’s “deconstructed” Peer/Client model enables horizontal query scaling without impact on other queries or your transaction throughput.

Storage

A pluggable, durable service, not tied to any one compute node.

Query

Local to your application with immutable database snapshots.

Transactor

Handles writes — one point of truth for the transaction log.

Architectural primitives, not workarounds.

Built in Clojure

Persistent data structures, functional transactions, open data modeling, and a commitment to stability over breaking changes. As you’d expect from a Clojure system.

Immutable

Writes append facts instead of overwriting rows, so every past database value remains available for query, debug, and replay.

Natively distributed

Built from first principles as a distributed system. Tools like d/sync and the transaction report queue make it simple to build event sourcing and deal with propagation delay.

First-class history

Past states as first-class values. Audit trails, temporal queries, and point-in-time reads are all built in, not bolted on.

Reified transactions

First-class transaction entities enables querying your database’s history itself. Change data capture, out of the box.

E/A/V+T model

A triplestore-like information model allows tabular, graph, document, sparse, and hierarchical data to coexist without impedance mismatch.

Queries across time, made trivial

First-class transactions and immutable database values make "as of the time" searches simple.

(defn top3 [db] ; top 3 planets by moon count
  (->> (d/q '[:find ?name (count ?m)
              :where [?p :body/kind :planet] 
              [?p :body/name ?name]
              [?m :moon/orbits ?p]] db)
       (sort-by second >)
       (take 3)))

;; Across time:
(map top3 [(d/as-of db #inst "1979-12-31")
           (d/as-of db #inst "1999-08-01")
           db]) ; today
;; +------------+------------+-------------+------------+
;; | Date       | 1st place  | 2nd         | 3rd        |
;; +------------+------------+-------------+------------+
;; | 1979-12-31 | Jupiter 16 | Saturn   11 | Uranus   5 |
;; | 1999-08-01 | Uranus  21 | Saturn   18 | Jupiter 16 |
;; | today      | Saturn 291 | Jupiter 108 | Uranus  29 |
;; +------------+------------+-------------+------------+
;; Every moon discovered in 2023 -- just ask the log.
(d/q '[:find ?inst (count ?moon)
       :in $ ?log ?t1 ?t2
       :where [(tx-ids ?log ?t1 ?t2) [?tx ...]]
       [(tx-data ?log ?tx) [[?moon]]]
       [?moon :body/kind :moon]
       [?tx :db/txInstant ?inst]]
     (d/db conn) (d/log conn)
     #inst "2023-01-01" #inst "2024-01-01")
;; => [[#inst "2023-02-06" 12]
;;     [#inst "2023-05-01" 62]
;;     [#inst "2023-05-23" 1]]
;; What caused that buggy blip in our Uranus reports?
;; The query is fine with the latest data...
(d/q '[:find ?date ?citation
       :in $ ?uranus
       :where [?moon :moon/orbits ?uranus _ false] ; retracted at some point
       [?moon _ _ ?tx]
       [?tx :db/txInstant ?date]
       [?tx :source/citation ?citation]]
     (d/history db) [:body/name "Uranus"])
;; There's the bad data -- we were missing a moon for a couple years.
;;
;; | Date       | Event                                        |
;; +------------+----------------------------------------------+
;; | 1999-05-18 | Identified in reprocessed Voyager 2 imagery  |
;; | 2001-12-20 | IAU/MPC retracts it — no confirmable orbit   |
;; | 2003-09-03 | Hubble independently recovers the object     |
;; | 2005-12-29 | Named Perdita, IAU announcement              |
;; +------------+----------------------------------------------+
;; Which transaction contains the greatest number of Saturn's moons?
(->> (d/q '[:find ?instant (count ?moon) ?citation ?url
            :keys date num-moons-discovered citation url
            :where [?saturn :body/name "Saturn"]
                   [?moon :moon/orbits ?saturn]
                   [?moon _ _ ?tx-entity] ; query the actual transaction
                   [?tx-entity :db/txInstant ?instant]
                   [?tx-entity :source/url ?url]
                   [?tx-entity :source/citation ?citation]]
          (d/history db))
     (sort-by :num-moons-discovered)
     last)
;; => {:num-moons-discovered 62,
;;     :date #inst "2023-05-01T00:00:00.000-00:00",
;;     :url "https://iopscience.iop.org/article/10.3847/2515-5172/adbf87",
;;     :citation "Ashton/Gladman/Alexandersen/Beaudoin, CFHT
;;                'shift-and-stack' technique, from 2019-2021 imaging
;;                — 64 candidates, 62 confirmed as genuine moons"}
                  

Start building with Datomic!