You are deciding whether to hand a product build to an outside team, and whether that team understands SaaS or only understands websites. The difference is not the framework. It is tenancy, billing logic, permissions, and the discipline to ship something small enough to be proven wrong quickly. Here is how we approach it, and where we would tell you to go somewhere else.
Tenancy is the decision you cannot walk back
Every SaaS stores data belonging to customers who must never see each other's rows. There are three common shapes: a database per tenant, a schema per tenant, or a shared schema with a tenant column on every table. For most early products the shared schema wins on cost and on migration speed, but only if isolation is enforced somewhere other than developer discipline. Postgres row-level security, applied per connection, survives a tired Friday deploy. A WHERE clause someone remembered to type does not. If you go that way, check how it behaves behind a pooler: a session-level SET leaks across clients in transaction pooling mode, so the tenant has to be set inside the transaction that reads.
The leaks are rarely in the obvious endpoints. They turn up in background jobs running outside the request context with a service-role key, in a search index that received a flat copy of every document with no tenant field, in a cache key built from a record ID alone, in a CSV export, in a signed storage URL that outlives the session, and in admin tooling built in a hurry. Our baseline test seeds two tenants and asserts that every route returns 404 rather than 403 for the other tenant's IDs, because a 403 confirms the record exists.
Then the details bite. Is an email address unique globally or per workspace? What happens when one person belongs to two customer accounts? Can you delete a single tenant's data on request without hand-writing SQL against production?
Billing is product logic, and it fails quietly
Subscription billing looks like a checkout button and behaves like a distributed system. Stripe holds one version of the truth, your database holds another, and they drift. The pattern that holds up: never gate a feature on a price ID read live from the payment API at request time. Keep your own entitlements table, updated from webhooks, so the product still works when Stripe is slow and so you can grant one customer an exception without inventing a new price.
Webhooks arrive more than once, out of order, and sometimes hours late. Handlers have to be idempotent on the event ID and reconcile against the current subscription state rather than assume a sequence. Plan changes mid-cycle mean proration. Seat-based plans mean the seat count moves daily, and somebody has to decide whether removing a user credits anything. Under European strong customer authentication rules a renewal can fail asking for 3D Secure rather than being declined, and the dunning email has to say something different in that case.
Usage metering adds its own class of bug. Events need idempotency keys or one retried job doubles a customer's bill. Aggregation windows have to match the invoice period exactly, time zone included, and the billing periods are UTC even when your dashboard is not. And you need an answer for the support email saying the dashboard shows one number and the invoice another, which means keeping the raw events, not only the totals.
Roles, invites and the support surface nobody scopes
The demo path is one founder logging in and seeing their own data. The real product is a workspace with an owner, a few members, an invite sent to the wrong address, someone who left the company last month, and a customer who wants a read-only seat for their accountant.
Permissions get expensive when they arrive late. A flat role enum (owner, admin, member) is a reasonable first version and carries most B2B products a long way. What breaks it is the first request for object-level rules, for example a member who can edit their own projects but only view everyone else's. If that request is likely in your market, model permissions as a single check function from day one, even if it returns true for every admin today, because the retrofit means auditing every query and every UI branch by hand.
Then the parts founders forget to brief: invite expiry and re-invite, email change and verification, session revocation when someone is removed, API tokens with their own scopes, and support impersonation. Impersonation is the one to build carefully. It saves hours of confused back-and-forth with customers, and it is also the most dangerous feature in the product, so it needs a persistent banner, a time limit, read-only access by default, and a log line recording who impersonated whom and when.
Ship the version you expect to throw away, and know what you cannot
The first release will be wrong about something important: the pricing unit, the core object, or which user actually cares. That is not a failure of specification. It is what shipping is for. So the work is to make version one small enough that being wrong is cheap, while being deliberate about the few things that are expensive to add afterwards.
Usually safe to defer: SSO with SAML and SCIM (your first enterprise buyer will ask, and will normally wait), granular RBAC, an in-app notification centre, a public API with versioning guarantees, mobile apps, real-time collaboration, extra languages, and any infrastructure more complicated than one managed Postgres and one deployable app. Microservices before product-market fit buy nothing except deploy coordination.
Painful to retrofit: tenant scoping, as above. An append-only audit log, because you cannot reconstruct history you never wrote, and the first security questionnaire or disputed deletion will ask for it. Stable external IDs instead of exposed sequential primary keys, which also stops a competitor counting your customers from an invoice URL. UTC timestamps, created and updated, on every table. Migrations that run forward automatically instead of by hand on a Sunday. And a restore you have actually run against a scratch database, since an untested backup is a belief, not a recovery plan.
Two people in Dijon, working with you entirely in writing
We are two. Robin Monteiro writes the code (Next.js, React, Postgres) and Florian Loppion handles the marketing side. We work from Dijon, in France, and that is the whole company: no account manager between you and the person typing, and no delivery team behind a curtain. If that sounds small for what you are planning, it may well be, and the next section is honest about when it is.
Everything runs by email and in writing. No calls, no video, no scheduled slots, not even as a fallback. For an international client that removes the worst part of hiring across borders: nobody in California takes a 3am call, and nobody in London or Bangalore waits for a European morning to unblock a decision. You send a question at the end of your day, you get an answer within 24 business hours, and that answer is text you can search eight months later when a new hire asks why the plan limits behave the way they do.
What you have to do differently: write the decision down instead of saying it, batch related questions instead of sending six one-line messages, and be explicit about acceptance criteria, because we cannot read a facial expression. Name one person who decides, since asynchronous work with a committee is slow. In exchange you get a written trail of every trade-off, a preview URL per change, and no hours spent in status meetings.
When a custom SaaS build is the wrong call, including with us
Do not commission a product before you have anything to sell. If you have not yet had a real buying conversation, a landing page and a Stripe payment link will teach you more in two weeks than a build will in three months.
If what you are describing is really a store, or a content site with accounts attached, use a platform. Shopify, Webflow and Squarespace run on monthly subscription plans, priced per site or per store, normally cheaper if you commit annually, and Shopify adds card processing on every order plus a transaction fee unless you use its own payment product. Check their pricing pages before you budget, because the tiers move. They will beat a custom build on time to launch and on the cost of keeping the thing alive for three years. Custom becomes rational when the business logic is the product, not the catalogue. For internal tooling, Retool or Airtable is usually the right answer until the seat count or the logic gets awkward.
Skip us entirely if you need engineers on call around the clock, a formal SOC 2 or HIPAA programme with an auditor, certified medical or payment core software, someone physically present in your office, headcount scaled to five engineers next quarter, or a partner sitting in your Slack answering within minutes. And if your way of working needs a weekly call to feel safe, we will frustrate you. That is a legitimate preference, not a flaw, and it is better discovered now than in month two.