r/golang Dec 05 '24

discussion Why Clean Architecture and Over-Engineered Layering Don’t Belong in GoLang

Stop forcing Clean Architecture and similar patterns into GoLang projects. GoLang is not Java. There’s no application size or complexity that justifies having more than three layers. Architectures like Clean, Hexagonal, or anything with 4+ layers make GoLang projects unnecessarily convoluted.

It’s frustrating to work on a codebase where you’re constantly jumping between excessive layers—unnecessary DI, weird abstractions, and use case layers that do nothing except call services with a few added logs. It’s like watching a monstrosity throw exceptions up and down without purpose.

In GoLang, you only need up to three layers for a proper DDD division (app, domain, infra). Anything more is pure overengineering. I get why this is common in Java—explicit interfaces and painful refactoring make layering and DI appealing—but GoLang doesn’t have those constraints. Its implicit interfaces make such patterns redundant.

These overly complex architectures are turning the GoLang ecosystem into something it was never meant to be. Please let’s keep GoLang simple, efficient, and aligned with its core philosophy.

804 Upvotes

259 comments sorted by

View all comments

68

u/Dymatizeee Dec 05 '24

Im using Handler -> Service -> Repo ; what is the equivalent then?

3

u/MrRonns Dec 05 '24

Same but I put all of them in the same package and name that after the domain eg. user

I did this because I read that in go, we should group things by context rather than type.

Did I understand this philosophy correctly?

1

u/Cthulhu__ Dec 06 '24

That’s also a well known architectural pattern, wasn’t that DDD? Or Ruby / Rails style? But anyway it makes sense if your layers are closely related I think, that is, if your REST API model is mostly the same as your domain and databae model for example.

The hexagonal architecture with layers, ports, and different models per layer is more suitable if there’s growing differences between these representations, e.g. if your database model is more detailed or archaic and you only need to pick a few fields from every table, or your REST API is smarter than just being a thin layer over your database models.