Why .NET and a modular monolith for a base you keep
A base you run for years is judged on year three, not the first hour. Here is the case for the runtime and the architecture shape behind Slicekit.
Most SaaS starters are tuned to win the first hour: how fast a route returns JSON, how few files stand between you and a deploy. That cost is real, but you pay it once. A base you intend to keep is judged on something else entirely: whether it is still good in year three, when the team is bigger, the load is heavier, and the thing you need to change is load-bearing code someone wrote eighteen months ago. Two decisions decide that outcome more than any feature does: the runtime you build on and the shape you give the architecture. Slicekit bets on a .NET 10 API and a modular monolith because both choices buy you the same thing: the option to still run, and still reshape, the system years from now.
What .NET buys you over the years
Throughput you do not have to engineer around. A compiled, JIT-optimised runtime gives predictable throughput and a small memory footprint under load. You are not reaching for a worker farm or a rewrite the first time real traffic shows up, and that headroom does not rot the way a clever caching layer does. The .NET community treats performance as a first-class concern, not an afterthought: the official blog’s most-read post of 2025 was a performance deep-dive, which tells you what the people maintaining the platform spend their attention on.
A strong static type system on each side. C# on the API and TypeScript on the SPA mean a wrong field, a renamed property, or a forgotten case fails at compile time within that codebase, instead of surfacing as a 2 a.m. incident. The type system does work for you on every change, not just the ones you remembered to write a test for. The two sides do not share a generated contract, so keeping the client in line with the API stays a deliberate discipline, which the typed client post gets specific about.
Coherent, single-vendor tooling on a long horizon. The SDK, the test runners, the EF Core migration story and the editor support are maintained together on one long support window. You are not assembling a build pipeline from a dozen packages that each move on their own schedule and break in their own way. The mature pieces Slicekit leans on (EF Core for persistence, Wolverine for CQRS and the outbox, OpenTelemetry for observability) are evidence of the same thing: an ecosystem that has already solved the boring, load-bearing problems.
Mainstream, hireable patterns. C# is stable and boring in the way infrastructure should be. The patterns Slicekit uses are well understood, and the people who know them are not a niche you have to outbid three startups to hire. A codebase you can still staff in three years is worth more than one that was fashionable this quarter.
Be fair: where Node wins
An honest argument names the other side. The Node ecosystem moves faster, the front-of-house hiring pool is larger, and serverless-first deployment is often a single click. If your product is a thin layer over a few APIs, or you are racing to a demo that decides whether the company exists next month, Node is a reasonable and even correct call. The bet only flips when the thing you are building is meant to last, and correctness under change, predictable cost under load, and a team you can grow start to matter more than time-to-first-route. Slicekit optimises for that second year on purpose.
Why a modular monolith, not microservices first
The runtime is half the decision. The other half is how you carve the system up, and here the fashionable answer is the wrong default. Splitting into microservices on day one buys you network calls, distributed transactions, and a deployment graph before you have a single paying customer, in exchange for independence you do not yet need. The pragmatic starting shape for early SaaS is a modular monolith: one deployable, with clear internal boundaries.
This is not a contrarian take. Martin Fowler’s MonolithFirst argument is that teams who start with a monolith and extract services later tend to do better than those who lead with microservices, because you rarely understand your boundaries well enough up front to draw them in the network. A modular monolith keeps the boundaries that matter, between modules, while paying none of the distributed-systems tax until you have a reason to.
And there are real reasons, eventually. The signals that one component should become its own service are concrete, not arbitrary: a component whose scaling needs diverge from the rest of the system, a team-ownership boundary that hardens as the org grows, or a genuine need for deployment independence so one team can ship without coordinating with another. None of those is a head count threshold or a line-count rule. They are conditions you notice when they arrive, and the right move is to extract then, with the boundary you have learned, rather than guess at it on day one.
The seams that make extraction cheap later
A monolith-first bet is only safe if breaking it up later is cheap. That is an architecture problem, and it is where the two halves of Slicekit meet.
React SPA
TanStack · typed client
.NET 10 API
vertical slices · CQRS
PostgreSQL
EF Core
RabbitMQ
outbox · events
Grafana
traces · logs · metrics
Slicekit is built from vertical slices: one feature, one folder holding its handler and validation, wired to a thin endpoint in the API host rather than logic smeared across layered service classes. Handlers are invoked over a Wolverine message bus rather than called directly, and the domain events an aggregate raises are published through a transactional outbox when the change commits. Those two facts are what keep later extraction tractable. Because a command reaches its handler over the bus instead of a direct method call, the same handler could later be hosted by a background worker or a separate service without rewriting it, and the architecture tests already forbid the core from depending on the web host, so nothing ties that logic to HTTP. Today Slicekit is a single deployable over one database, not a set of separately deployed modules. What it gives you is a system whose seams are drawn at the slice and event boundaries, so the day you have a real reason to split something out, the cut line is already there and already loosely coupled rather than something you have to carve out of tangled code.
The honest summary of the bet
None of this is the fastest way to a demo, and Slicekit does not pretend otherwise. The bet is that the expensive part of a long-lived product is not the first route but the hundredth change: that a predictable runtime, types that catch mistakes before users do, and an architecture whose seams are already drawn will save you more, over years, than a faster start saves you in a week. If your horizon is a weekend, that bet is a bad one. If you are building something you intend to run and reshape for years, it is the whole point.
If that is the bet you want to make, the introduction lays out what is in the box, and the architecture overview shows how a request flows from the browser to the database and back.