If you found this article, than you are probably similar to how I was a few months ago. I started a project in Go that required a SQL backend and I wanted to use any tool that would help me build this backend quickly. I stumbled upon entgo (an ORM for Go) and decided to give it a try.
Initially it was easy to setup and get started. The code generation seemed to work well and in no time I was using the database in my application. Everything was going well, but I ran into a few issues I could not over look:
- Auto Migration Failures
- "Magical" Queries
- Code Bloat
Auto Migration Failures
The auto migration feature of module seems to have issues processing fields with date/time
values. After I spent hours debugging I reached out to their community to see if anyone had this issue. I received no response in their Discord (does not seem very active) and I only received one response on a Github issue I posted on the topic (after over a month of the issue being posted).
"Magical" Queries
During load testing on my application I began noticing performance issues from the database. When I began using the Debug()
mode for the entgo client I observed overly complex queries, even for simple cases (i.e. simple SELECT
s, no JOIN
s. Some of these issues may be resolved by modifying the code generation options of the library but that seems like quite a bit of additional effort for an issue that should not exist.
Code Bloat
The included ent
code generation tool could use some optimization, reviewing many of the files reveals many included functions and complex logic that (as I understand it) adds little value unless advanced features of the library are being used (GraphQL integration, Custom Hooks, etc).
What to use instead?
I just told you all of the reasons why not to use entgo, but what should you use? Honestly, raw SQL or really a raw SQL schema and raw queries with sqlc for Go code generation. That may sound counter intuitive, but hear me out. sqlc
is not an ORM, you still write your database schema, perform your migrations, and write your own queries. sqlc
handles the generation of Go interfaces to perform those queries in a type-safe fashion within your application. This has a few advantages over entgo
(or any ORM for that matter):
- No "Magic" Queries
- No Auto Migration System Failures
- Minimal Code Generation
No "Magic" Queries
You write all of the queries yourself, so you can easily make them as efficient as your SQL knowledge allows
No Auto Migration System Failures
You perform the database migrations yourself before sqlc
is ever called, it cannot cause migration errors if it does not perform migrations.
Minimal Code Generation
sqlc
generates 3 (minimal) files total as part of its tooling, regardless of the database schema or number/complexity of queries.
For all of these reasons above I am officially making the switch from using entgo
to sqlc
. If there is interest I can write about that migration in more detail, let me know what you think about that in the comments.
I hope you read this and have considered that an ORM like entgo
might not actually be the faster/easier approach to adding SQL queries to your application and that sometimes a simpler approach can be just as good, if not better.
Top comments (9)
what do you think about gorm.io/ ?
burn it with fire, 8 levels deep nested reflection source code, a beginner's nightmare
I have never dived into that project, but that source sounds like a nightmare. Is the use of reflection that only way to pull off a library like that?
yea it requires parsing from struct tags for your custom structs but the problem with gorm is struct tag abuse and so many reflection caused by it
If you wanna skip SQL for an interview and wanna do very basic non-relational CRUD, it is the only use case of it.
Else, most of prod codebases uses standard library paired with sqlx or pgscan or sqlc lightweight approaches that only scans SQL results to given 1-by-1 fields with minimal "sql" struct tag parsing or with the help of Go type assertions on sql package types
I see, good to know what can be found in more real-world scenarios for Go and SQL.
Don't trust words alone. ~35k stars for Gorm repo should tell you something.
You can also check performance benchmarks: github.com/efectn/go-orm-benchmark...
It's not the best and not the worst.
Reflection is just another tool, that you shouldn't afraid.
Same thing is for Gorm, if you know where and how to use - go for it.
If not - it can be a good reason to learn/investigate.
True, I believe my first comment on this thread touches on this very sentiment that Gorm generally is considered the ORM for Go. There is no doubt that Gorm is very popular and used in a wide range of project sizes. Does that mean it was the best tool for them to use? Maybe, as the same could have been said for my project highlighted in the post (within the ent context).
Reflection is a tool, one that developers often are confused by (myself included) but I do not think its use equates to a "bad" product inherently. I whole hardheartedly agree, that any tool a developer is interested but unsure about should be investigated for them in the context of their use cases.
there are also other issues that other people don't point out since everyone(35k stars) is OK with mediocre performance(which is fine as long as code is maintainable) and not explicitly using SQL. Most of ORM users come from hibernate background(java/c#) and use things like eager loading or preloading (implicit SQL joins) this doesn't work well in Go package structure as it creates cyclic pkg dependencies. It is actually bad due to entity embedding, it goes against the language philosophy but if your aim is to make a product that works with mysql/postgresql at the same time and wanna ignore some of dialect based SQL, go for it. Most businesses will never pick this approach, furthermore gorm doesn't cover every SQL scenario like full text search. The inertia that devs built up by themselves in this last 10 years with ORMs is very dangerous as it creates a maintenance burden, your project can be as good as your dependecy, don't believe so much in the stars count
On the surface it is an amazing a truly amazing ORM tool that seems to have a very active and helpful community. Personally, I would avoid the using it for many of the same reasons as to why I have stopped using
entgo
, it vastly complicates the code base and has great potential to be used improperly/inefficiently. Do you have personal experience with Gorm?