Mostly when you need a ledger like functionality to your data. Datomic preserves the history of all the changes by design so it is very easy to reconstruct the history of changes to your data.
If this describes the majority of your problem space then Datomic is a good fit. Otherwise I would stick to a popular RDBMS like Postgres to leverage the community behind it. You will have a much easier time interacting with a well understood open source engine.
I think this is true - you will have an easier time not blazing new trails in general - but the need of ledger-like functionality isn't the distinguishing factor.
Preserving the history of all changes isn't just for reconstructing that history later, it's a central component in maintaining ACID while allowing for distributed readers.
Datomic has a singular transactor - node that can accept writes. So all transactions happen in sequence and consistency is maintained within the data model.
With normal databases, when DB'' is created, DB' is lost. You change stuff in place. This means that anyone wanting to observe a consistent view of the database needs to coordinate with writes. This is why SQL dbs are single giant machines.
For Cassandra, Dynamo, Mongo, etc you still change stuff in place, but you just accept that things will be potentially inconsistent ("eventually consistent") for your readers. Once you drop that part of ACID you can scale your readers and your writers arbitrarily.
With Datomic DB, DB', and DB'' are still maintained. If you want to read the database "now" you can get a handle to the state that your reader thinks is the most recent. This might not be behind the absolute newest state that the transactor knows about, but it is still a consistent view of the database.
Its because of this you can scale your read nodes independently of the system. Because if you are reading DB' you know the value of that won't change you can load chunks of the indexes into the memory for caching and even embed the querying into the application making queries.
The proprietary-ness and JVM-ness of Datomic are its biggest weaknesses. I choose to believe those weaknesses can be addressed.
Ah yes, makes me remember the amazing talk by Rich Hickey called "The database as a Value" [1]. I felt like my brain was reorganized after watching it.
The simplicity of Datomic is very appealing, it's just a timestamped series of EAV entries, and some fancy indexing. Avoiding the latency (the database over there issue) sounds like a big win. Most of the simplicity is made possible by only having one single synchronous writer which is a major drawback you have to be able to live with. Some write-heavy applications would struggle.
Related to the timetravel feature I've bookmarked a blog post by Valentin Waeselynck where he talks about some of the misconceptions and drawbacks. [2]. My company have a not super-great setup with triggers on MySQL, and have longed for MariaDBs SQL 2011 compliant Temporal Tables which looks very interesting [3]. I guess an advantage with Datomic is that you don't have to create an entire table history row when all you want is to update a single field.
I was interested enough in Datomic that I started building a Python bridge but never finished it [4]. An added bonus was that I learned about the Transit serialization format which was ALSO super inspiring [5].
This is true but it's a false premise. You have history but it's clunky to work with.
You won't be able to "source" and recreate the past without some work and unexpected things will happen when you "source" the past with the most recent code.
It useful but the history aspect is easily misunderstood.
Oh, yeah, think of event sourcing. You have a series of events leading up (aggregate) into some state.
This can be done in different ways but with Datomic you can request a point in time database. This database doesn't exist so it needs to be "sourced" from history. This means running through everything that happened up to some point to create a snapshot of the database state (or query).
As the world stands today, it makes sense to use Datomic if you are writing code on the JVM and are willing to pay for the database and associated support.
In a hypothetical future world where the data model and query approaches have more widespread open source adoption it is competitive for a lot of the same use cases.
In addition to what was said, Datomic Cloud automates a lot of the annoying and difficult to suss deployment for application dev, not just the database. You can deploy large scalable apps in minutes and easily deploy new code in minutes with no down time (or architecting a deployment system yourself).
Datomic is elegant and it has some interesting properties like temporal. This is a huge win for many cases where business logic needs them (e.g. finance). I think it would make more sense for clients also running JVM. I don't have much experience with it but it looks very good. -- a SQL engine dev
What I've find most useful is the immutable nature of the database. That within a reactive framework for UX is great combination. You get really cool things to happen with little effort.
Also, because the database is a value. You can easily do mock data and isolated transactions locally to experiment and test. This makes some things easier.
Another cool thing is how you do cross database queries by simply passing multiple databases to a function. It will pull in the subset of the dataset needed to compute the query result. It's that easy to do.
It's not good at dealing with high volume transactions (a lot of writes) it's not too bad but it's not built for that primarily.
First, everything is an entity, so you can enrich attributes with information about how they should manage PII/SPI data. There's nothing built-in but you can build meta models easily.
Second, if you really have stringent requirements you would encrypt the data that is to be protected and throw away the encryption keys when the data needs to be purged.
Datomic does allow you to opt out of history so the keys would not be recoverable in that case.
Or, you just excise the data, at which point the information will be purged from the database. It's not instant, index rebuilds and garbage collection need to take place before it's really gone.
You're in control. The fact that you have history isn't a problem.
If anyone is interested, I am attempting to revive an open source clone of Datomic called EVA.
As is the original codebase works fine, its just unmaintained. My hope is to clean up the code, make an HTTP layer for a remote peer, and make a Rust embedded peer so that this sort of Database can finally escape the JVM.
My goal of developing Datalevin is to replace our use of both Datomic and Postgres, so we have a single DB. The aim is to provide a versatile database that meets data needs of most use cases.
I mention Sqlite in README because I have not finished the query engine rewrite of Datalevin, so the query performance is not up to my standard of being competitive with relational databases for large data sets. However, even at the current state, Datalevin is already faster than the alternative Datalog stores in the Clojure world for the most part.
Finally, since you seems to want to go into this space, I will mention that: without some new tricks in query algorithms, triple stores would be always slower than standard relational DBs. This is not a solved problem. Just be aware what you are getting yourself into.
Can anyone else get beyond the 2nd level? I am getting stuck because it returns the values in slightly different order than is expected. And I don't see a way to report an issue via the website.
30 comments
[ 3.6 ms ] story [ 86.8 ms ] threadIf this describes the majority of your problem space then Datomic is a good fit. Otherwise I would stick to a popular RDBMS like Postgres to leverage the community behind it. You will have a much easier time interacting with a well understood open source engine.
Preserving the history of all changes isn't just for reconstructing that history later, it's a central component in maintaining ACID while allowing for distributed readers.
Datomic has a singular transactor - node that can accept writes. So all transactions happen in sequence and consistency is maintained within the data model.
So your database goes
DB (0 transactions) -> DB' (1 transaction committed) -> DB'' (2 transactions committed)
With normal databases, when DB'' is created, DB' is lost. You change stuff in place. This means that anyone wanting to observe a consistent view of the database needs to coordinate with writes. This is why SQL dbs are single giant machines.
For Cassandra, Dynamo, Mongo, etc you still change stuff in place, but you just accept that things will be potentially inconsistent ("eventually consistent") for your readers. Once you drop that part of ACID you can scale your readers and your writers arbitrarily.
With Datomic DB, DB', and DB'' are still maintained. If you want to read the database "now" you can get a handle to the state that your reader thinks is the most recent. This might not be behind the absolute newest state that the transactor knows about, but it is still a consistent view of the database.
Its because of this you can scale your read nodes independently of the system. Because if you are reading DB' you know the value of that won't change you can load chunks of the indexes into the memory for caching and even embed the querying into the application making queries.
The proprietary-ness and JVM-ness of Datomic are its biggest weaknesses. I choose to believe those weaknesses can be addressed.
The simplicity of Datomic is very appealing, it's just a timestamped series of EAV entries, and some fancy indexing. Avoiding the latency (the database over there issue) sounds like a big win. Most of the simplicity is made possible by only having one single synchronous writer which is a major drawback you have to be able to live with. Some write-heavy applications would struggle.
Related to the timetravel feature I've bookmarked a blog post by Valentin Waeselynck where he talks about some of the misconceptions and drawbacks. [2]. My company have a not super-great setup with triggers on MySQL, and have longed for MariaDBs SQL 2011 compliant Temporal Tables which looks very interesting [3]. I guess an advantage with Datomic is that you don't have to create an entire table history row when all you want is to update a single field.
I was interested enough in Datomic that I started building a Python bridge but never finished it [4]. An added bonus was that I learned about the Transit serialization format which was ALSO super inspiring [5].
You won't be able to "source" and recreate the past without some work and unexpected things will happen when you "source" the past with the most recent code.
It useful but the history aspect is easily misunderstood.
This can be done in different ways but with Datomic you can request a point in time database. This database doesn't exist so it needs to be "sourced" from history. This means running through everything that happened up to some point to create a snapshot of the database state (or query).
In a hypothetical future world where the data model and query approaches have more widespread open source adoption it is competitive for a lot of the same use cases.
Also, because the database is a value. You can easily do mock data and isolated transactions locally to experiment and test. This makes some things easier.
Another cool thing is how you do cross database queries by simply passing multiple databases to a function. It will pull in the subset of the dataset needed to compute the query result. It's that easy to do.
It's not good at dealing with high volume transactions (a lot of writes) it's not too bad but it's not built for that primarily.
Not really a good fit for today's world of privacy regulations, where deletion of data should be possible and guaranteed.
https://docs.datomic.com/on-prem/reference/excision.html
https://docs.xtdb.com/language-reference/datalog-transaction...
First, everything is an entity, so you can enrich attributes with information about how they should manage PII/SPI data. There's nothing built-in but you can build meta models easily.
Second, if you really have stringent requirements you would encrypt the data that is to be protected and throw away the encryption keys when the data needs to be purged.
Datomic does allow you to opt out of history so the keys would not be recoverable in that case.
Or, you just excise the data, at which point the information will be purged from the database. It's not instant, index rebuilds and garbage collection need to take place before it's really gone.
You're in control. The fact that you have history isn't a problem.
As is the original codebase works fine, its just unmaintained. My hope is to clean up the code, make an HTTP layer for a remote peer, and make a Rust embedded peer so that this sort of Database can finally escape the JVM.
https://github.com/bowbahdoe/eva
If you want to use something open source today that has the same query language but a different data model, https://xtdb.com/ is high quality.
I would really like a pure Rust version of Datomic for embed use cases.
There is all also Datahike, that is going in that direction too. It is maintained and actively developed.
https://github.com/replikativ/datahike
My goal of developing Datalevin is to replace our use of both Datomic and Postgres, so we have a single DB. The aim is to provide a versatile database that meets data needs of most use cases.
I mention Sqlite in README because I have not finished the query engine rewrite of Datalevin, so the query performance is not up to my standard of being competitive with relational databases for large data sets. However, even at the current state, Datalevin is already faster than the alternative Datalog stores in the Clojure world for the most part.
Finally, since you seems to want to go into this space, I will mention that: without some new tricks in query algorithms, triple stores would be always slower than standard relational DBs. This is not a solved problem. Just be aware what you are getting yourself into.
Okay.