
Key Takeaways
- 1What a modular monolith is and why small teams should start there
- 2What microservices really cost a small team
- 3Monolith vs modular monolith vs microservices: comparison table
- 4When to use microservices: signals that it is time to split
- 5How to build a monolith that can split later
Whatever you choose, we build it around your business
Off-the-shelf tools force your business to adapt to their workflow. JK Tech Hub develops custom software as per your exact requirements - you own the code, pay no per-user fees, and get GST-ready solutions supported from Rajkot, India.
Quick Answer
A small team should build a modular monolith, not microservices. One deployable application with clear internal module boundaries gives you most of the organisational benefits of microservices with a fraction of the operating cost. Microservices add a network, distributed data, per-service pipelines and observability that a team under about 15 engineers cannot staff properly. Split only when a specific module needs its own scaling, release cadence or technology, and split that one module first. Roughly 9 out of 10 products under 50 engineers never need more than three services.
This guide is for founders, CTOs and lead developers at companies with one to fifteen engineers who are deciding how to structure a new product or an ERP-style system, or who are being told that microservices are the modern default. It explains what a modular monolith is, what microservices really cost a small team, and which signals mean it is time to split. By the end you will be able to choose a structure and explain the reasoning to investors, clients or your own team.
What a modular monolith is and why small teams should start there
A monolith is a single deployable application: one codebase, one build, one process or a set of identical processes behind a load balancer, usually one database. A modular monolith is the same thing with discipline added. The code is divided into modules such as orders, inventory, billing and users, each with its own public interface, and modules talk to each other only through those interfaces, never by reaching into each other's tables or internal classes.
That discipline is what people usually want when they ask for microservices: clear ownership, code that one developer can understand, and the ability to change billing without breaking inventory. A modular monolith delivers it without a network between the modules. A function call replaces an HTTP call, a database transaction replaces a distributed saga, and one deployment replaces twelve.
The cost of a modular monolith is discipline. Nothing physically stops a developer from importing another module's internals, so you enforce boundaries with code review, linting rules that block cross-module imports, and a folder structure that makes the boundaries obvious. Small teams are actually better at this than large ones because everyone can see the whole codebase.
What microservices really cost a small team
Microservices are not a code organisation choice. They are an operations choice, and the bill is paid in engineering time every month, not once at the start. This is what a team takes on the day it splits a product into services.
| Cost item | Monolith | Microservices | Who pays in a small team |
|---|---|---|---|
| Deployment pipelines | One | One per service, plus coordination | Whoever is best at CI, and it becomes their job |
| Data consistency | Database transactions | Eventual consistency, sagas, idempotent handlers, duplicate events | Every developer, on every feature that touches two services |
| Local development | Run one app and one database | Run many services or mock them; onboarding takes days | Every new hire and every laptop |
| Debugging | One log, one stack trace | Distributed tracing, correlation IDs, log aggregation | Whoever is on call at 2 AM |
| Testing | Integration tests in one process | Contract tests, environment per service, flaky end-to-end suites | QA and the developer who wrote the feature |
| Infrastructure | One server or a small container setup | Orchestration, service discovery, secrets per service, network policy | An engineer who becomes a part-time platform team |
| Hosting bill | Lowest | Each service has a minimum footprint; typically 2 to 4 times higher at small scale | The company |
| Cross-cutting changes | One pull request | Several pull requests in dependency order, version compatibility | Product velocity |
A rough rule from our own delivery data: a team that splits a product into eight services before it has ten engineers spends between a quarter and a third of its engineering time on the plumbing in the table rather than on features. That is the equivalent of hiring two or three developers and having them work on nothing customers can see.
Monolith vs modular monolith vs microservices: comparison table
| Criterion | Plain monolith | Modular monolith | Microservices |
|---|---|---|---|
| Deployable units | One | One | Many |
| Code boundaries | Weak or none | Enforced module interfaces | Enforced by the network |
| Data | One shared database | One database, module-owned tables | Database per service |
| Team size that fits | 1 to 5 | 1 to about 30 | Several teams, each owning services |
| Independent scaling | Scale everything together | Scale everything together, or run the same build in different roles | Per service |
| Independent releases | No | No, but modules can be feature-flagged | Yes |
| Technology per component | One stack | One stack | Any stack per service |
| Failure isolation | One failure can take down all | Same, mitigated by multiple instances | Partial failures, but more failure modes |
| Operating cost | Low | Low | High |
| Migration path | Hard to split later | Modules extract cleanly into services | Hard to merge back |
When to use microservices: signals that it is time to split
The correct question is never whether to use microservices, but which module has earned the right to become a service. These are the signals we look for, and any one of them applied to a specific module is a reason to extract that module. None of them applied to the whole product at once is a reason to extract everything.
- One module has a very different load profile: a report generator, an image processor or a notification sender consumes 80% of the CPU while the rest of the app idles. Extracting it lets you scale that work on its own hardware.
- One module needs a different release cadence: a payments or compliance module must change under audit and slowly, while the rest of the product ships daily. Separate services allow separate change controls.
- One module needs a different technology: a machine learning component in Python inside a TypeScript product, or a component that must run on a specific runtime. This is a legitimate reason and a common first split.
- Team structure has actually changed: you now have two or more teams that step on each other in the same codebase and block each other's releases. Splitting along team lines works; splitting in anticipation of teams that do not exist yet does not.
- A hard isolation requirement exists: a regulated customer or a security review requires that certain data and code run in a separately controlled environment.
- Build and test time for the monolith has become a daily blocker: a 40-minute pipeline for a one-line change, after you have already tried caching, parallelism and test pruning.
Things that are not signals: a conference talk, an investor asking about scale, a new hire's preference, or the belief that microservices are what serious companies do. Serious companies with hundreds of engineers use microservices because they have hundreds of engineers.
How to build a monolith that can split later
The fear behind most premature microservice decisions is that the monolith will become a tangle that can never be split. That fear is justified for a plain monolith and unjustified for a modular one. These habits keep the exit door open.
- One folder per module with a small public interface file, and a lint rule that forbids importing anything else from another module.
- Module-owned tables: each module reads and writes only its own tables. When a module needs data from another, it calls that module's interface. Cross-module joins are the first thing to ban.
- Events inside the process: when orders are placed, the orders module publishes an in-process event and the inventory module subscribes. Later, that event bus can be replaced by a message queue without changing the subscribers.
- Separate background work from web requests: a worker process that runs the same build with a different entry point is the cheapest possible form of independent scaling and needs no new service.
- Containerise from day one so the application already runs the way a future service would. Our Docker and Kubernetes services page describes the setup we use, and most of it stays on a simple container platform for years.
A monolith built this way is extracted one module at a time by moving the folder into its own repository, replacing the in-process interface with an API client and the in-process events with a queue. Each extraction is a two to four week project for one module, which is a manageable cost when a signal from the previous section appears.
Microservices for startups: the exceptions
There are startups for which services from day one are correct, and it is worth naming them so the advice above is not read as absolute.
The first is a product whose core is a pipeline of clearly different workloads, such as ingesting large data feeds, processing them and serving results, where each stage has a different scaling profile from the start. The second is a founding team that has run microservices together before, owns the platform tooling already and has more than a handful of engineers. The third is a product that must integrate a mandated third-party runtime that cannot live in the main process.
Even in these cases the number is usually two to four services, not twenty. If your architecture diagram for a pre-revenue product has more boxes than the team has people, the diagram is the problem.
What JK Tech Hub has seen building ERPs for small and mid-sized companies
Most of our ERP and business-software work is for companies with 20 to 500 staff: manufacturers in Gujarat's casting, forging, bearing and pump clusters, distributors, hospitals, schools and a growing number of overseas clients in the US, UK, UAE, Australia and Europe who reach us through our international page. Almost all of those systems are modular monoliths, and we build them from Rajkot with teams of two to six developers per project.
A manufacturing ERP for a casting unit in the Metoda GIDC area is a representative example: production planning, inventory, purchase, sales, quality, GST billing and payroll as separate modules in one application with one PostgreSQL database. About 70 users, one container platform, deploys twice a week. In four years the only piece that was extracted into its own service was the report and PDF generation module, because month-end reports were slowing the web requests for everyone else. That extraction took three weeks.
We also inherited a distribution management product from another vendor that had been built as eleven services for a company with four in-house developers. Every feature touched three or four services, local setup took new developers most of a week, and a single failed message consumer had silently stopped stock updates for two days before anyone noticed. We merged nine of the services back into a modular monolith over five months, kept two that had real scaling reasons, and the client's release frequency went from monthly to weekly. Our ERP development page covers the kinds of systems where we apply this approach.
How to decide
If your team has fewer than about 15 engineers, build a modular monolith with the habits above and revisit the question when a specific signal appears. If you already run microservices and they are costing you velocity, merging most of them back is a real option, not a failure. If a single module clearly needs separate scaling, cadence or technology, extract that one and leave the rest alone. Match the number of deployable units to the number of teams you actually have.
Related reading and next step
- ERP development for manufacturers and distributors
- SaaS product development with a structure that scales
- Docker and Kubernetes services
- Writing an SRS that defines module boundaries early
- Hire developers in India for your product team
If you want an architecture review of an existing system or a modular monolith designed for a new product, send the details through the contact page or on WhatsApp at +91 7265004040 and we will reply with a fixed quote within two working days.
Tags
Continue exploring
Pages on JK Tech Hub related to this article.
