Atlas: Goodbye
Atlas is a great tool to manage your database schema declaratively but the free version is missing crucial features and the whole concept falls short when it comes to manage schemas for multiple DBMS
- tags
- #Db #Dbms #Migrations #Schema-Management #Atlas
- published
- reading time
- 6 minutes
First of all, I’d like to point out that I’m not saying Atlas is not a great product! If I would start a greenfield SaaS product next week, I would definitely still consider Atlas! The issues I’ll address in this article revolve around blind spots - whether they’re intentional I dare not say - in the free version of Atlas, particularly when the product is designed to work with multiple database management systems (DBMS).
Context
Even though I am a software developer already for a few years and of course used databases almost all the time, I normally approached data persistence most of the time like a second level concern. Something like
don’t bother me with details, the ORM is taking care of that 🤷♂️
boils it down quite nicely.
Most of the time, that’s fair and especially in the company where I used to work, most applications were “create, read, update, delete” (CRUD) apps anyway, so, why bothering about database specifics, right? At some point I might be able to write about Supabase, PostgREST and friends to give a different perspective on CRUD apps, but today is not this day. Ironically, especially with Supabase and PostgREST, you will also look much more into database related details than you probably do today.
Currently, I’m working on a private project in Go.
I am using sqlc to generate the type safe boilerplate code for SQLite and PostgreSQL from predefined SQL queries.
I have a few database tables, probably something around 10-15 and - coming from ORMs - I figured, having some tool that at least manages my schema, creates migrations and everything, should save me some time.
In the end, I can’t even say if I actually saved anything at all or if I could’ve picked random coding LLM and let it generate the migrations for me and would’ve been done faster.
Shortcomings
When I say “shortcomings”, I’m mostly complaining about features that were decided to be behind a paywall. By itself, that is not a good or bad thing, we’re all software engineers, we want/need to make money, it’s only natural that, if you want ’the good stuff’ you should be paying for it! So, I absolutely get, why for instance support for Microsoft SQL Server, ClickHouse and many more “enterprisy” DBMS are pro features whereas Postgres, MySQL and SQLite are also supported in the free version.
But, even though Postgres support is “free”, only some features are actually free while others are “pro” features and therefore must be paid for. I was aware of this, before I started the project, but I figured, shouldn’t be much of a problem, I’m not doing anything fancy, do I? If you check the features overview for database features, you might realize - most likely quicker than I did - how these limits became quite annoying.
I was reviewing my login logic, when I realized, I didn’t handle case-sensitivity for usernames in my code.
And while I already thought about where I should call strings.ToLower(...) in my code, to ensure I covered it properly without convoluting the code too much, it hit me “isn’t there anything the DBMS could help me with instead of doing it all in the code?”.
And in fact, there is!
For SQLite there is collate nocase and for Postgres there’s even a custom column type citext!
“Problem” with Postgres is, citext is an extension that needs to be enabled.
If you checked the link above you might’ve noticed already, extension management is a pro feature of Atlas, bummer!
And if you now think, no problem, then simply create a trigger that ensures usernames are always lowercase?!
NOPE! Triggers are a pro feature as well, of course!
As a last resort, I created (or let create 😇) some SQL script that checks for the extensions I need and installs them as part of the migrations.
Unfortunately, this still breaks Atlas’ capability to create migrations because when it ramps up a dev database to compare my (HCL) schema against the latest state of the database, it fails, because citext is not available when Atlas parses the schema.
I thought about trying to hack around that, but eventually I just let it go.
Not only because of the (lack of) aforementioned pro features but also because of the second issue I had with Atlas.
Multi-DBMS support
Atlas supports a variety of DBMS:
| Driver | Availability |
|---|---|
| PostgreSQL | Open |
| MySQL | Open |
| MariaDB | Open |
| SQLite | Open |
| TiDB | Open |
| LibSQL | Open |
| SQL Server | Pro |
| ClickHouse | Pro |
| Redshift | Pro |
| Oracle | Pro |
| Spanner | Pro |
| Snowflake | Pro |
| Databricks | Pro |
| CockroachDB | Pro |
(see docs link above)
It is also possible to configure multiple schemas in a single Atlas config, for example by using multiple environments. However, when exploring this further, you will notice that it is not possible — or at least I haven’t found a good way — to maintain one HCL schema and generate migrations for both PostgreSQL and SQLite from that single schema.
Perhaps I still hold onto the ORM concept of mapping one “object model” to multiple database schemas, but I wonder if it’s time to let go. At some point, I started questioning whether maintaining two distinct schemas still offers an advantage—or if it would be better to manage migrations manually.
The issues began with column types and concluded with specific sqlc(...) statements to configure default behavior for a column.
I understand that some things are hard to abstract and I wouldn’t mind to conditionally include/exclude certain resources based on the current “engine”. However, maintaining the same schema across multiple database management systems (DBMS) makes scalability challenging. With the rise of LLMs, you can either write one migration yourself and “convert” it to the second dialect with the help of an LLM or you can directly generate all migrations with a LLM and only review them afterwards. The advantage is, this way you need a lot less tool specific knowledge (e.g. How do I create a trigger in Atlas?) and you don’t need to tell your LLM how to get to the Atlas documentation but you can rely on the solid SQL knowledge of all coding LLMs and ‘it just works’ ™.
Conclusion
Atlas is not a bad tool or anything per se. If you’re developing a SaaS product that only needs to support one DBMS and you have the budget for a pro plan, Atlas could be an excellent tool for you. It simplifies migrations — such as with its Kubernetes Operator — and prevents schema drift between your development environment and production database through built-in drift detection. It offers a lot for the right use case, but unfortunately, my typical scenario doesn’t fit that profile.
Scope of the tool aside, I reached a point where I don’t want to check whether this or that feature that I need for my project is also supported / available in the tool, that should help me save time by managing my database migrations. If Atlas ever re-thinks their licensing to really make PostgreSQL and SQLite support free and ships better multi-DBMS support I might reconsider, but for the time being, I’m done with Atlas