← Back to blog

Why Multi-Tenant and Bespoke Can't Share a Codebase

· 3 min read
Why Multi-Tenant and Bespoke Can't Share a Codebase Why Multi-Tenant and Bespoke Can't Share a Codebase

Running AIREP and Gripswich OS side by side has taught me that 'reusable' and 'bespoke' pull in opposite directions, and pretending otherwise just produces worse versions of both.

<p>I run two systems that look similar from a distance and are actually opposites. AIREP is meant to be a productized, multi-tenant ERP — one codebase, many businesses, each with their own database, but fundamentally the same product underneath. Gripswich OS is the opposite: a platform built for one gym, GRIPswich Bouldering, shaped specifically around how that business runs. Same stack, same author, same general problem space of small-business operations. Completely different design philosophy.</p><p>The temptation, when you're building both at once, is to try to make them share more than they should. You write a quoting module for AIREP and think, well, Gripswich needs something like invoicing too, surely I can reuse this. Sometimes you can. Often you can't, and the attempt to force it costs more than just writing it twice.</p><p>The reason is that bespoke software is allowed to make assumptions. It knows exactly who's using it, what their roster looks like, how their memberships work, what their edge cases are, because there's one customer and you can just ask them. Productized software can't make those assumptions. Every assumption you bake in is a constraint on the next tenant who doesn't fit it. So the two systems end up optimizing for opposite things: Gripswich OS gets to be sharp and specific, AIREP has to be general and configurable. Configurability has a cost — it's slower to build, slower to extend, and every feature needs to be thought about in terms of "how does this work for a business I haven't met yet."</p><p>What's made this clearer to me is having both running at the same time instead of one after the other. If I'd only ever built bespoke platforms, I'd probably over-generalize the next one out of habit, adding configuration options nobody asked for because that's what felt professional. If I'd only ever built AIREP, I'd be tempted to force Gripswich's specific workflows into the generic ERP shape just because the shape already exists. Doing both simultaneously keeps each one honest. When I'm in Gripswich OS and I catch myself adding a settings toggle for a feature only GRIPswich will ever use, that's a smell — bespoke software doesn't need toggles, it needs a direct implementation. When I'm in AIREP and I catch myself hard-coding an assumption that's true for the first tenant but might not be true for the second, that's the actual productization work: finding the places where "this one customer's way of doing it" needs to become "a thing every tenant can configure."</p><p>I think a lot of small software businesses get this wrong in one direction or the other. Either they build fifty bespoke systems for fifty clients and drown in maintenance because nothing is shared, or they build one over-engineered platform too early and spend all their time on abstractions nobody's using yet. My instinct, for what it's worth, is that you want bespoke first and productized second, in that order, even if you're planning to run both — because the bespoke build is where you learn what actually matters to a real operator, and the productized build is where you decide which of those lessons generalize and which were just quirks of that one business.</p><p>The database-per-tenant decision I made for AIREP is part of this same thinking. It's a concession that even within "productized," tenants are going to diverge — their data volumes, their customization needs, eventually maybe their own schema quirks. Rather than fight that with one shared schema and a thousand conditional branches, I gave each tenant room to be itself at the data layer while keeping the application layer common. It's not a universal answer, but it's the version of productization I trust: shared where sharing is cheap, separate where separation is honest.</p>

Comments

No comments yet — be the first!

Leave a comment

Comments are held for moderation before appearing.