
Writing code isn't the bottleneck anymore, reading is
This week I was working on one non-critical feature that seemed simple at first sight. 50k lines of code later, it seemed to work as expected. In a side project, or a service where “nobody will be upset if it’s dead and kills everything around”, it would be ready to ship. But for a production-grade project, the risk of an outage is too big to skip reading the code.

How to Know If your Software Is Overcomplicated or Oversimplified?
Quick takeaways Complexity comes from two extremes - projects fail both when they’re overcomplicated with unnecessary patterns and when they’re oversimplified for a complex domain Essential vs accidental complexity - essential complexity comes from the domain itself and can’t be removed, accidental complexity is created by poor implementation choices “Keep it simple” is lazy advice - achieving simplicity takes effort; closing your eyes to complexity just pushes it elsewhere Match patterns to the problem - using the same approach everywhere is a red flag; mix simple solutions for simple parts and sophisticated patterns for complex domains Ship fast and iterate - if you can’t deploy daily and fear making changes, something is wrong regardless of whether it’s over or under-engineered Introduction We discuss where complexity in software projects comes from and how to deal with it.
Series
Popular articles
- The Go libraries that never failed us: 22 libraries you need to know
- Safer Enums in Go
- Common Anti-Patterns in Go Web Applications
- How to implement Clean Architecture in Go (Golang)
- The Repository pattern in Go: a painless way to simplify your service logic
- Introduction to DDD Lite: When microservices in Go are not enough
Tags
- golang
- go
- watermill
- ddd
- domain-driven design
- events
- software-development
- event-driven
- clean-architecture
- web-applications
- anti-patterns
- architecture
- ci
- firestore
- cloudrun
- gcloud
- googlecloud
- microservices
- serverless
- testing
- agents
- ai
- databases
- devops
- firebase
- gitlab
- reactive
- repository
- building-business-applications
- building-in-public
- cqrs
- development-process
- frameworks
- kafka
- mysql
- nats
- pipelines
- software-architecture
- transactions
- amqp
- authentication
- backend
- balance
- basics
- bounded-context
- c4
- cicd
- code-quality
- code-review
- complexity
- design-patterns
- diagrams
- docker
- dry
- e-book
- efficiency
- enums
- event-storming
- gamedev
- generics
- google-cloud
- grpc
- htmx
- iteration
- javascript
- learning
- libraries
- metrics
- modular-monolith
- monolith
- open-source
- openapi
- over-engineering
- overengineering
- parallelism
- product-engineering
- productivity
- programming-languages
- prometheus
- pull-requests
- python
- rabbitmq
- retrospective
- security
- software-design
- software-engineering
- sql
- sse
- startups
- strategic-ddd
- swagger
- terraform
- tips
- unpopular-opinions
- versioning
- work-culture