Writing
Your Team Size Should Influence Your Architecture
An architecture diagram doesn’t show who gets paged when an arrow stops working. The right design meets the business’s needs and leaves the team with work it can carry.
By Ka Lun Chan · Architecture / Leadership
Every design comes with someone to carry it
An architecture diagram shows boxes and arrows. It doesn’t show who gets paged when one of the arrows stops working at two in the morning, or who spends a Thursday upgrading the same library in nine repositories.
I’ve spent more than 23 years building software across VoIP, publishing, SaaS and government applications. Most of that time I’ve led small teams of two to six engineers, and I’ve helped grow teams from five people to thirty. I’ve worked in Rails and Django monoliths and in microservices on AWS, with CI/CD pipelines and teams spread across time zones. When someone proposes a new design, I ask a practical question early: who is going to carry this?
Team size should influence architecture because every architecture creates ongoing work: deployments, monitoring, security updates, incident response and ownership. The right design meets the business’s requirements and fits the structure of the team, and the team has to be able to operate it.
The cost after the code ships
Building a service is the part everyone estimates. The rest arrives afterward and stays for as long as the service runs:
- An owner who knows how it works and decides how it changes
- A deployment pipeline, kept working when base images and runners change
- Monitoring and alerts tuned well enough that people trust them
- Security patches, dependency upgrades and secrets to rotate
- Incident response, with someone who can debug it under pressure
- Documentation that stays current enough to help the next person
Each item needs a person with time to do it. A design review that only estimates implementation is pricing the smallest part of the bill.
A hypothetical five-person team considering twelve services
Picture a five-person team running a B2B SaaS product as a single application. The codebase is getting crowded, and someone proposes splitting it into a dozen services: accounts, billing, orders, notifications, reporting, search and six more.
Here’s what their week would look like afterward.
A feature that touches orders and billing now means two pull requests in two repositories, an API contract change between them, and a deploy order someone has to remember. A security fix in the web framework becomes twelve upgrades, each with its own pipeline run. A slow checkout request crosses four services, so finding the cause needs distributed tracing that somebody has to set up and maintain.
On-call changes most. Five people now cover twelve services. Either everyone learns enough about all twelve to handle a page, or the rotation depends on whoever built the service that’s failing. When the engineer who knows billing goes on vacation, billing changes wait.
Every hour spent on that work comes out of the same five people’s week. Features, customer support, infrastructure and production problems all draw on one pool of attention, and a small team feels each new obligation right away.
The split could still be worth it. Suppose reporting jobs were slowing the customer-facing app and needed to scale on their own. Suppose a large customer required payment data to sit behind a separate security boundary. Suppose the company planned to double the team and form a second team around one domain. Each of those is a business reason to extract a service. If two or three of the twelve candidates had a reason like that, I’d extract those and keep the rest together.
The modular monolith as a deliberate choice
A modular monolith is one deployable application with firm internal boundaries. Each module owns its data and exposes a small interface, and checks in CI stop other modules from reaching into its internals. Rails engines and Django apps both support this way of working.
The team keeps one pipeline, one place to debug and database transactions that still work. The boundaries do the organizing that services would otherwise do. If a module later needs to become a service, the seam is already there, and extracting it is a contained project. I’ve written about that path in more detail in how I decide whether a microservice should be a microservice.
When separation earns its cost
Microservices solve real problems, and as teams grow those problems become common. Separation tends to pay for itself in four situations:
- Independent scaling: one workload has a very different load profile, such as batch processing next to a request-and-response app.
- Release cadence: one area changes daily and another needs slower, more careful releases.
- Security isolation: payments, authentication or regulated data benefit from a smaller blast radius and tighter access.
- Stable ownership: a team will own the service long term, with backup coverage, not just whoever wrote the first version.
At thirty engineers, the coordination cost of one shared codebase can outweigh the operational cost of several services. Teams waiting on each other’s merges and releases is a real problem, and service boundaries that match team boundaries can fix it.
Headcount is one input among several
Team size matters, but it doesn’t decide the question alone. A six-person team handling payments, heavy data processing and strict uptime requirements may need more separation than a twelve-person team building a simple internal tool. I also look at:
- Domain complexity, and whether the domains have clear edges
- Reliability requirements, and what an outage in one area costs the business
- Skills, especially operating containers, cloud networking and observability
- Organizational boundaries: who reports where, which teams sit in which time zones
What architecture does to the organization
Architecture decides how much people have to coordinate. It decides whether a new engineer can run the product on a laptop in the first week or spends that week wiring up a dozen services. It decides whether on-call is shared fairly or falls to the two people who understand the most moving parts.
It also decides how much depends on individuals. Every service only one person understands is a single point of failure, the same as a server with no backup. Removing those is a large part of how I lead engineering teams, and the architecture either helps with that or works against it.
When to revisit the decision
I don’t use a headcount threshold as the trigger. I watch for problems the team can see:
- Releases regularly wait on unrelated changes from another group
- One workload’s load or failures keep affecting everything else
- Incidents keep landing in the same part of the system
- A compliance requirement calls for a hard boundary
- A team is forming around a domain and is ready to own it
When one of those shows up, the conversation has evidence behind it. The same logic runs the other way: a set of services that always change together can be merged back. I wrote about how my own thinking moved across these patterns in what different systems taught me about software architecture.
A short decision checklist
Before adding a service, I want clear answers to five questions:
- What problem are we solving?
- Who owns the service, including backup coverage?
- What delivery or operational benefit will we gain?
- What ongoing work are we adding?
- Why is this the right time?
If the answer to the second question is “the team” or one person with no backup, the service isn’t ready.
Short answers
Should a small team use microservices?
Usually only for a few specific parts of the system. A small team carries every service’s deployments, monitoring, upgrades and on-call. Extract a service when it solves a named problem, such as independent scaling, security isolation or a team ready to own it, and keep the rest in a well-structured application.
What is a modular monolith?
A modular monolith is one deployable application with firm internal boundaries. Each module owns its data and exposes a small interface, which keeps operations simple and makes it easier to extract a service later if the evidence calls for it.
When should a team move from a monolith to services?
When observable problems appear: releases waiting on unrelated changes, one workload affecting everything else, repeated incidents in one area, a compliance boundary, or a team ready to own a domain long term. Headcount alone is not a good trigger.
Choose what your team can sustain
The best architecture for a team is one it can run well on an ordinary week and still debug at two in the morning.
Choose an architecture your team can sustain while it meets the business’s needs, and change it when the evidence supports the change.
That might mean a modular monolith for years, a few well-chosen services, or a gradual move to many. The answer should follow the team and the business, and it should be revisited as they grow.