Frustrations with Crystal ORMs

yujiri8 profile image Ryan Westlund Updated on ・3 min read

As I said in my Crystal review, I got into Crystal in the hopes of using it for Didact, as it had a more suitable ecosystem than Rust.

But now that Didact is released and I'm trying to refactor my own website's code to use it, I'm realizing even more inadequacies in the ORM library I'm currently using than I thought. Here are the inadequacies of Granite:

  • Most model methods do not actually get the benefits of type checking, one of the core benefits of ORMs, because they use wildcard keyword arguments so you can pass literally anything to them. But it's worse than that: a lot of things aren't even runtime errors! For example, you can pass an argument for a nonexistent field to the where method and it's silently ignored.

    I looked into fixing this myself, but it seems pretty complicated - it would require a substantial overhaul of how those methods are implemented. If it was the only issue with the library I'd put in the time to figure it out and do it, but it's not, meaning I'm too unsure that I'll stick with Granite anyway to put that much into it.

  • Association collections (the property exposing the many side of a one-to-many relationship) cannot be queried! They just return an Array, so you can't filter or sort with relationships.

  • The deeply questionable architecture of database connections being part of model definitions, so it's impossible to use a model with multiple database connections.

  • The "generate create table SQL from model definition" feature is not usable for my use case because it doesn't treat foreign keys at all, only basic fields and types. It actually doesn't even support NOT NULL columns right now except for the primary key, and my PR to fix that has been hanging for two weeks.

    This may turn out not to be an obstacle if I do end up switching to SQLite. But I'm still not sure about that, especially since, while I see how to implement my conlang's Word model (which currently uses Postgres arrays of translations and tags) without arrays, I don't see how Granite's query builder could be used to implement that since I don't see a way to filter a model based on its relationships.

  • No feature to delete records without fetching them first.

So there are a lot of issues with Granite. I absolutely adore the thought of a 2000-line ORM, but...

So I've checked out at least two other Crystal ORMs.


Around 8000 lines, but much more features than Granite.

Sole reason for rejection: it's Postgres only. I don't want to lock myself out of switching to SQLite.


Around 10000 lines (ugh), and install instructions want me to let Jennifer pollute my directory structure a bunch, but it wasn't too hard to figure out how to set it up without that.

Has the same problem as Granite with not being able to query relationships!

UPDATE: I was wrong about this. See my correction.

Ugh. None of them suit my needs and the ones where my needs are in-scope have unresponsive maintainers :(


Editor guide
edwardloveall profile image
Edward Loveall

Have you checked out the Lucky Framework? It's focused on being as type-safe and fast as possible, including the ORM. We have an active Discord. It's a whole framework of course, not just an ORM but it might be a good fit for what you're trying to do.

yujiri8 profile image
Ryan Westlund Author

I looked at Lucky early on before I decided on Kemal as an API framework. I believe in the separation of ORM and API libraries, and I don't believe in OOP API frameworks.

edwardloveall profile image
Edward Loveall

Fair enough! Thanks for giving it a look, and good luck with your project 🙂

andyrosenberg profile image

I’ll probably give Clear a shot on my next Crystal project. Also it’s sad to know the Amber/Granite folks are being unresponsive, wasn’t like that a year ago.

yujiri8 profile image