This is a long overdue post, and I'm going to expedite it because otherwise I'll never post it. There's a heated debate going on right now about microservices vs. monoliths and I'm here to introduce you my answer.
BEHOLD. THE PRAGMALITH.
A Pragmalith is boring. It's a way to build your app that embraces your ability to fuck up and tries to minimize the impact of your mistakes. It also recognizes that discipline is hard, so why not force good practices on us?
Pick the edge cases and bugs that you know rather than having to discover new ones. Treat innovation like a rare and precious gem. Read Choose Boring Technology and pass it around.
Document things. Write comments. Write tests. Don't SQL your prod database. Put safeguards in place to save you from the day you'll be too tired to care about discipline.
Do things the boring way. Clever code won't save you CPU cycles but it will kill many brain cells — including yours when you'll come back to it after a year.
(It may also cause hair losses via forced pull action).
Backends and frontend have different lifecycles. Keep them separate to minize risks. It will also prevent some spaghetti shortcuts where build backend logic in your views.
This here is the only rule where I'm calling for something specific. And this is coming from my experience. I worked as a dev and as a product manager and I'm absolutely convinced that separating the frontend cycle from the backend cycle works best for everyone (I can expand more on this if you really want to — just ask in the comments).
If you think you need a new microservice then you probably don't need it. New services or repositories should be painkillers, not vitamins.
E👏v👏e👏r👏y👏 new service will add a new set of 👏pro👏blems. Testing, deploying, backing up, testing the backups... Adding more services is expensive and brutal. And it should be weighed against a real pain felt today (slow release cycles, devs stepping on each other, etc...)
A Pragmalith is not just about how you structure your services. It's about having a certain mindset where you try to minimize headaches and avoid unnecessary complexity.
Do the things you have to, not the things you want to.
Monoliths have their own problems at scale and you'll need to break them up at some point. But really, it's about being pragmatic and do things that work for you.
I don't trust myself to have the discipline to avoid shortcuts in the code. That's why our backend is a REST API in a separate codebase: it has clear inputs and outputs, and you can't cheat in the views. The separation of concerns is forced on us.
- Rails 5 API backend with Postgres
- React* for the web app frontend
- React Native* for the mobile app
- Gatsby for the website
- A Rails microservice for the Jira Connect App
* Items with a star mean an innovation token was used at the time
React was a new framework at the time, thus being an expensive innovation token to use. BUT, it was going to remove a lot of pain for our small team. We could re-use a lot of the web app code for the mobile app, and once I got the hand of React it became quite easy to approach Gatsby.
But all the other stuff is boring. I really want to try Elixir and Phoenix, to learn more about Kubes, to explore all that AWS has to offer. But it would kill us.
We'd have an exciting tech but a boring product.
A Pragmalith is something that works for you and your org. The threshold of what's boring moves with the competencies and experience of the team.
I'm out ✌️