DEV Community

ShandonCodes
ShandonCodes

Posted on

Stop using entgo...please

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 SELECTs, no JOINs. 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)

Collapse
 
blinkinglight profile image
M

what do you think about gorm.io/ ?

Collapse
 
mrwormhole profile image
Talha Altınel

burn it with fire, 8 levels deep nested reflection source code, a beginner's nightmare

Collapse
 
shandoncodes profile image
ShandonCodes

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?

Thread Thread
 
mrwormhole profile image
Talha Altınel • Edited

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

Thread Thread
 
shandoncodes profile image
ShandonCodes

I see, good to know what can be found in more real-world scenarios for Go and SQL.

Thread Thread
 
helgi profile image
Oleg

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.

Thread Thread
 
shandoncodes profile image
ShandonCodes

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.

Thread Thread
 
mrwormhole profile image
Talha Altınel • Edited

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

Collapse
 
shandoncodes profile image
ShandonCodes • Edited

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?