Building a multi-tenant SaaS: what TrainerFoundry taught us
Inside the engine room of TrainerFoundry: a modular monolith, tenant isolation, two separate money flows — and five lessons for your own SaaS.
Anyone commissioning a SaaS platform wants to know whether their provider would stand behind the same decisions themselves. With TrainerFoundry, software for personal trainers, we do exactly that: at Tech42 we build and run our own product for people who spend a surprising share of their week on admin rather than training. Under the hood, TrainerFoundry is a multi-tenant SaaS in which every trainer runs their business in a separate, isolated tenant. Below: our decisions, and the lessons for your own SaaS project.
The problem: four tools for one job
A self-employed personal trainer needs client management, a calendar, payments and a steady stream of prospects — often four tools plus spreadsheets. TrainerFoundry brings scheduling, payments, a client CRM, a lead pipeline and an early warning for client churn together in one platform. The trainer works in one interface, their clients in a second, mobile-first app. For the trainer that means less admin: their clients book themselves, automatically get an invoice in the trainer’s name for every card payment, and TrainerFoundry takes no commission on their payments.
The stack at a glance
- Backend: .NET 10 and EF Core 10 on Azure SQL, one application on Azure Container Apps.
- Frontends: two React 19 progressive web apps plus an Astro 5 marketing site.
- Identity: Azure Entra External ID.
- Payments: Stripe for our own billing, Stripe Connect for clients paying their trainer.
- Hosting: Microsoft Azure, data centre region Germany West Central (Frankfurt).
Lesson 1: a modular monolith goes further than you think
TrainerFoundry consists of eight business modules that run together in one process and share one database. Project references, not network calls, enforce the module boundaries: a module can only reach another module’s code through defined interfaces and notifications.
Microservices would have multiplied the operational overhead without a driver: one team, one customer profile, one runtime. We cover the general trade-off in modular monolith vs. microservices; the discipline lives in the module boundaries, not in the deployment topology.
Lesson 2: tenant isolation belongs in the infrastructure
In TrainerFoundry every organisation is a tenant. The obvious, dangerous approach is to remember the organisation filter in every query. We turned that around: a global query filter in the shared data-access base class restricts every tenant-scoped table to the signed-in user’s organisation, and saving stamps the organisation automatically. Anyone building a new feature does not have to establish the separation — they would have to actively work around it. That is the right way round for a security boundary.
Lesson 3: two money flows that sound the same
TrainerFoundry has two completely separate payment systems. In the first, the trainer pays us for their subscription — through our own Stripe account and under our tax registration. In the second, their clients pay them for sessions and packages — through the trainer’s own Stripe Connect account, under the trainer’s tax registration and with invoices in the trainer’s name.
Both systems have subscriptions, invoices, tax and a currency. That is exactly what makes them dangerous: the words are identical, the owners are not. A question about tax on the trainer’s subscription can easily — and very plausibly — be answered with facts about the trainer’s invoices to their clients. So one simple rule applies: every ticket, code comment and piece of customer-facing copy about money, tax or invoices states explicitly which of the two flows it means. Separate webhooks and code areas enforce the split.
Lesson 4: two audiences, the same words
Every screen, email and legal text addresses either the trainer, our customer, or the trainer’s clients — with a different sender, different rights and often a different language. Because both sides use the same words, code and its tests can look correct and still address the wrong person. So every change answers who is this for? explicitly, before anything is built.
Lesson 5: four countries are more than a translation
TrainerFoundry launches in Germany, Austria, Switzerland and Australia — in euros, Swiss francs and Australian dollars. The trainers’ invoices to their clients must therefore cover four tax systems, each under the trainer’s own tax registration. Our own subscription invoices to trainers run under a single tax registration: ours, in Germany. Three decisions have held up:
- Stripe Tax calculates the tax on every invoice — in both money flows. Whether it is a trainer’s invoice to a client or our subscription invoice to a trainer, the tax amount comes from Stripe.
- Region is a fact, not a preference. Users pick their language; the region follows from the country. A Swiss trainer who prefers English gets English text with Swiss formats.
- Documents remember their language. A trainer’s invoices to clients keep the language they were issued in; a later language switch rewrites nothing.
What this means for your SaaS project
If you decide to build a SaaS of your own, answer five questions before the first line of code:
- Who is the tenant? The organisation, a team or the individual user?
- Where is isolation enforced? In every query, or in the infrastructure?
- How many money flows are there? And who is the merchant of record in each?
- Which audience gets which texts? With one unambiguous sender and recipient.
- Which countries and currencies at launch? Tax and formats depend on it.
These five questions matter whatever your industry or stack.
Conclusion: where multi-tenant SaaS really goes wrong
None of these lessons from TrainerFoundry is spectacular, and that is the point. The expensive mistakes in a multi-tenant SaaS rarely come from choosing a framework; they come from places where two things share a name and differ: two tenants, two money flows, two audiences, two languages. An architecture that makes those differences explicit — in code, tests and vocabulary — goes further than any technology choice.
Tech42 builds SaaS platforms for mid-sized businesses — from software architecture through multi-tenancy and payment integration to operations on Azure. If you are planning a product of your own, our custom software development is the right place to start. We can work out which of these lessons apply to your project in a free initial call — no strings attached.
Keep reading
Related articles
-
October 19, 2024
Modular monolith vs. microservices: which architecture fits your project?
Microservices sound modern — but they're not the right call for every project. A sober comparison of both architectures, with clear recommendations for when to use which.
Read article -
August 30, 2024
Storing secrets and keys securely with Azure Key Vault
API keys, passwords, and certificates don't belong in config files or source code. How Azure Key Vault centralises sensitive data securely — and how we wire it cleanly into .NET applications.
Read article -
March 23, 2024
Software Erosion: A Silent Threat to Long-Term Software Quality
Software erosion costs more long-term than any single bug. How to spot it early, what the silent decay really costs, and how to stop it.
Read article