Someone asked whether or not acid-state
was production ready. I shared my experiences:
parsonsmatt [11:32 AM] @nikolap it's used by cardano-wallet and Hackage. Based on my experience with acid-state, I'd say it is not a good choice for production data storage. For local desktop apps, SQLite is a much better choice, and for real production apps, Postgresql is king.
parsonsmatt [11:44 AM] acid-state did not have a test suite, at all, until I implemented the very first tests (for TemplateHaskell code generation) earlier this year. It has picked up some tests since then, but I'm still not confident in it's correctness.
It claims to be resilient to unplugging the power cord, but I doubt that, as it's not resilient to Ctrl-C
: acid-state/acid-state#79
Migration errors are extremely difficult to identify and debug. Modifying a function that is makeAcidic
-ified or any datatype involved in an acidic function will cause problems recovering from a database, unless you check all SafeCopy
instances (most of which will be derived) and make appropriate migration instances. None of this is compiler-checked, and it's caused a major and difficult-to-fix bug in almost every single release of cardano-wallet
. You get an error message that is basically "Error decoding type: not enough bytes" where type
is the first new field that fails to decode after you've added to some record or some function. It's awful.
The data storage format is a binary blob, so you need to use Haskell to view or edit the data, and you need to use the right version of whtaever acidic record you're using. If you fucked up the schema, this means git checkout old-commit-with-working-schema
, recompiling, and reloading GHCi. With a different solution (eg SQL db), you can view raw data by using eg pgsql
command line SQL client and do arbitrary queries on it. Since the on-disk data format has a schema, you can ask a SQL database whether or not the Haskell type is compatible, and if it isn't, you get a detailed table-vs-record incompatibility report.
acid-state
strongly encourages a top-down nested tree sort of data storage. This is efficient if you work top-down, but if you need any kind of relational query, then your performance is going to be absolutely awful. Additionally, it uses Haskell functions on Haskell datatypes, whereas a dedicated database is going to be hyper optimized C code operating on super efficient data structures for queries. You can kinda recover SQL-like querying and performance by using ix-set
and storing tables of data with foreign key references, but now you're just reinventing SQL poorly so that you can use less efficient data structures in Haskell.
Oh, and the entire record must be kept in memory. So if you have 13GB of application state, you need 13GB of memory, minimum, and this is all kept in live memory that the GC must walk over every cycle. So performance is bad compared to an on-disk solution. You can implement record sharding on top of acid-state to help this problem, but it's fragile and brittle and infects your data schema, and you might as well use something else.
The benefits are just... really small, and the costs are massive. It's not a good choice.
Related: acid-state is not ACID because it ignores fsync errors (#175)