the architecture an intern would understand
there are only two hard things in computer science:
0_ cache invalidation;
1_ naming things;
2_ off-by-one errors.
i don't know who came up with this joke, but i think every dev has heard some version of it 😂
let's name a few things today! let's talk monolith, monorepo, microservices, and why this matters more now in times of AI.
let's go (:
git diff: monolith, monorepo and microservices
a monolith is when your whole application is a single thing. a backend that does everything, a deploy that ships everything together, a process that runs everything. if one part breaks, the rest can go down with it. imagine a restaurant where the same employee waits tables, cooks, washes dishes, and works the register. it works when it's small. when it grows, it gets complicated.
microservices is the opposite. you take that restaurant and split it: one team just cooks, another just waits tables, another handles the register. each one works independently, communicates with the others through messages (APIs, queues, events), and can be updated or scaled separately. if the register breaks, the kitchen keeps running. the complexity moves somewhere else, communication between these services, but each piece is smaller and easier to understand on its own.
a monorepo is just where you keep the code. it's an organizational decision, not an architectural one. the repo is the drawer. what you put inside is another story.
big companies like Google and Meta work with monorepos. Google keeps an absurd amount of code in a single repository, but inside that repo there are thousands of independent services. in other words: monorepo (organization) and microservices (architecture) are independent decisions. you can combine either one with the other.
a monorepo makes it easier to share code across teams, keep dependencies consistent, and make changes that affect multiple services at once. it's easier to refactor when everything is in the same place than when you have to open pull requests across 15 different repositories.
so why do smaller companies usually split across multiple repositories?
first, because a monorepo at large scale requires heavy tooling, sophisticated CI/CD*, and processes that small teams usually don't need. for a team of 3, having one repository per service can be simpler.
second, and this is a point that goes unnoticed: access permissions. if you hire a freelance dev to work just on the frontend, with separate repositories you only give access to that repo. in a monorepo, that person has access to everything, scraper, business logic, infra, API keys someone forgot to put in .env...
access control is one of the main reasons multirepos are still popular, because there is no solution for access control in monorepos.
commit to main
we spend a lot of time trying to fit what we build into categories that were designed for completely different contexts. monolith vs. microservices is a debate that makes sense when you have 20 devs and daily deploys. when it's just you and your coffee at 11 pm, the question is different: can i maintain this? can i come back to the code after a week focused on another freelance gig and understand what's going on?
and people have been taking this simplicity to the extreme for a while now. Pieter Levels, who built Nomad List and RemoteOK, runs products with millions of users on a ridiculously simple setup: a single PHP file, one server, jQuery on the front. Marc Lou does something similar with Next.js. no microservices, no orchestration. minimal necessary complexity to solve the problem and move forward.
that doesn't mean this is the right answer for everyone. but when a solo dev making serious revenue uses an architecture an intern would understand, maybe we should be humble enough to realize that a lot of what we learn in college and working for big companies is, honestly, optional.
there are many ways to build a house. with an engineer and an architect, with just a master builder, even a group building an ecovillage. the materials, technique, maintenance all change... but in the end what matters is the house being built and serving the residents. software is the same thing.
git cherry-pick: AI reads better when the code is together
when the entire project's context is in the same place, AI can navigate between services. understand how the scraper feeds the database, how the database feeds the front, and suggest changes that make sense for the entire system.
with separate repositories, AI only sees the piece you opened. it's like asking for advice from someone who only read chapter 3 of the book. they try to help, but the context is missing.
the tools we use to code are changing fast, and the way we organize our code needs to keep up. it's no longer just about readability for humans. it's about readability for humans and AI at the same time.
a heads-up: AI is a copilot, not autopilot. learning speed goes way up when you treat each suggestion as a starting point to understand, not as a final answer.
git rebase: bringing everything together in one place
i decided to adopt a monorepo for the auction search engine. in a few hours i brought everything together into a single repository: scraper, property deed reader, and front. organized with pnpm workspaces, which is a way to have multiple "projects" in the same repo, each with its own dependencies, but linked together. think of a house with independent rooms that share the same kitchen.
and with that full context view, the mess showed up quickly. with access to all the pieces of the puzzle, AI pointed out things that would've taken me a long time to notice on my own.
there were scripts pointing to files that didn't exist. references in package.json to code that hadn't even been written yet. and worst of all: i had a package.json trying to do everything, spin up the server, run scrapers, process PDFs, geocode addresses. it was the technical equivalent of that restaurant employee who waits tables, cooks, washes dishes, and works the register. remember them from above? yeah.
cleaning up the mess, i looked at the result and thought: is this a monolith?
no. each service has its own package.json, its own dependencies, its own tsconfig. the scraper runs on its own schedule with node-cron. the deed reader exports a function: takes a PDF URL, returns structured data, and that's it. the API spins up separately. they are independent processes living at the same address. monorepo, but not monolith.
and here's the point that goes beyond monorepo vs. multi-repo: distributing the system into separate services doesn't solve confusion. it just spreads it around. if you can't define clear boundaries within a single repository, creating fifteen repositories won't magically bring that clarity. the mess just gets harder to find.
git diff: how the pieces connect without knowing each other
in real microservices, services communicate via HTTP, queues, and events. here the integration is simpler: the database.
the scraper writes to Supabase. the API reads from Supabase. the deed reader processes the PDF and returns the data to whoever called it, without writing anywhere. each piece only knows the database. no piece knows the others.
is it a microservice in the formal sense? no. is it a monolith? not either. it's something in the middle. and for a solo dev building a product, that "in the middle" is exactly where i need to be. formal microservices would mean separate deployments, queues, orchestration, and every bug would cost three times more to debug. for a one-person team, that's overhead that brings zero value back.
i'm not in the middle because i'm too small to do it "right". i'm in the middle because it's where i have the most clarity. and clarity, for someone building alone, is the most valuable resource there is.
other branches
i've been meeting a lot of people who have never coded before and are taking a shot now with AI, kind of vibe coding, kind of not... either way it's really cool to see designers and product people shipping their first deploys with that sparkle in their eyes of someone who just put something live for the first time.
last week i co-hosted an AI co-building session in Ho Chi Minh City, "Ship Happens".
the idea:
3 focused hours building together, with a timer. before starting, everyone tells the table what their goals are for the time block, and everyone works on their project in silence. during breaks, sharing tools and feedback.
at the end, a 2-minute mini pitch for anyone who wants to show what they did. all levels, even people who have never opened a terminal. [link]
and for next week... how about organizing mini tech events in your city for women's day? here's the event i'll be co-hosting in Ho Chi Minh for some inspiration. [link].
Until the next commit, Michelle (:
__
*CI/CD is what happens between you doing git push and the code running in production. CI (continuous integration) is the automated part that runs after the push: a server (like GitHub Actions) installs dependencies, runs tests, checks if the code compiles. if anything fails, you get a heads-up before anything goes live. CD (continuous deployment) is the next step: if CI passed, the deploy happens automatically.
if you use Vercel for the front, you already have CD working without realizing it, every time you push to main Vercel builds and deploys. what's probably missing is CI running tests before letting the deploy happen. without that, if the code has a bug, it goes live and you find out when you open the site (or worse, when a user finds out). with CI, the deploy only happens if the tests pass. it's an automated safety net. the cost is writing the tests, which is where most people get stuck, but CI itself is just a configuration file in the repository. (: