← Insights
build

How We Build B2B SaaS That Scales to Series B

The architecture decisions that let you close a Series B are different from the ones that let you ship in 6 weeks. Here's how to do both without rebuilding twice.

Most B2B SaaS is spec'd for the first 100 customers. The architecture decisions that let you close a Series B are different from the ones that let you ship in 6 weeks. Here's how to do both.

The answer is not "design for scale from day one." That produces over-engineered systems that take too long and cost too much before you've validated anything. The answer is making the 6-week decisions in a specific order, with specific constraints, so that the decisions that cost the most to reverse are made correctly the first time.

This is how we build every serious B2B platform. Not a methodology document. The actual decisions, in the order they matter, with the reasoning and the failure modes of the alternatives.

Data model: domain first, not UI first

The most expensive mistake in B2B SaaS is modeling the database after the first version of the UI. The UI is a hypothesis. The domain model is (or should be) a description of the business. When the UI changes — and it will, within the first 90 days of real customers — a UI-driven schema requires migrations and refactors in places they shouldn't be needed.

We start with a domain model session before any code is written. The output is a set of entities, their relationships, and their lifecycles. Not tables — entities. What is a Project? What is an Account? What is a Subscription? What are the state transitions each entity can be in?

The schema is derived from the domain model, not from the wireframes. The API is derived from the domain model. The UI is derived from the API. This ordering matters because it determines what needs to change when assumptions are invalidated.

Specifically: use domain events as a design primitive even if you're not building full event sourcing. Write down what happens in the domain as events — invoice.created, subscription.upgraded, user.invited. This creates a canonical vocabulary, surfaces integration points with external systems early, and provides the basis for audit trails and webhooks without retrofitting them.

API design: REST vs. GraphQL vs. tRPC — when each is right

We do not have a religious position on this. We have criteria.

REST is the right choice when: external clients will consume the API (partners, customers building integrations), the team already knows REST deeply, the access patterns are resource-centric and relatively simple. REST ages well. A well-designed REST API from 2018 is still a good API in 2026.

GraphQL is the right choice when: the frontend has highly variable data requirements (different views need deeply different shapes of the same data), you have multiple frontend clients with meaningfully different needs, and you're willing to invest in schema design, resolvers, and a caching strategy (GraphQL caching is not free like HTTP caching is). The failure mode is schema sprawl and N+1 query problems in resolvers when not using DataLoader properly.

tRPC is the right choice when: the frontend and backend are in the same TypeScript monorepo, there are no external API consumers, and developer velocity on the happy path is the dominant concern. The tradeoff is tight coupling between frontend and backend — refactoring a backend procedure requires the frontend to update in the same commit. This is fine for internal applications; it's limiting when you need to expose the API externally.

The decision we make most often: REST for the external-facing API (webhooks, partner integrations, eventual public API), tRPC for the internal frontend-backend communication in a TypeScript stack. The two can coexist in the same application.

Auth: why rolling your own is still wrong in 2026

We don't build authentication infrastructure. We use Auth0, Clerk, or WorkOS depending on the product's needs. This is not a vendor preference — it's a risk-adjusted engineering decision.

Custom auth implementations fail in specific, predictable ways: token expiry not handled correctly, password reset flows with timing vulnerabilities, session fixation on login, insecure password storage for edge cases in the migration path from an old system. These are solved problems. A dedicated auth service has solved them, has been audited, and has a security team monitoring for new attack patterns.

The decision between providers is based on requirements:

Clerk: developer experience-first, excellent for products where the authentication UI is end-user facing and needs to be polished with minimal integration work. B2C or prosumer B2B. Less strong on enterprise SSO complexity.

Auth0: mature, flexible, strong enterprise SSO support (SAML, OIDC, multiple IdP configurations per organization), good audit logging. More configuration overhead. The right choice when enterprise customers will bring their own IdP.

WorkOS: purpose-built for enterprise B2B — SSO, Directory Sync (SCIM), Audit Logs as first-class features. If your Series B target customers will require SOC 2 compliance and enterprise SSO, WorkOS earns its cost by being the only auth provider where enterprise compliance features are the main product.

The failure mode of spending engineering time on custom auth is not usually a security breach (though it can be). It's the opportunity cost: 3–4 weeks of engineering on auth infrastructure is 3–4 weeks not spent on the product differentiation that drives growth.

Multi-tenancy: which model for which product

This decision gets made once and is expensive to reverse. We covered the full tradeoff space in detail elsewhere, but the summary we apply to every build:

Shared schema with row-level security (Postgres RLS): the right default for products under 500 tenants, relatively uniform data volumes per tenant, and a team that will apply RLS policies correctly at the database level — not just WHERE tenant_id = ? in application code.

Schema-per-tenant: the right choice when tenants need meaningfully different configurations, when data isolation needs to be demonstrable structurally (for compliance reviews), or when the operational investment in schema-migration tooling is warranted by the business model.

Database-per-tenant: reserved for enterprise-only models where contractual data isolation and data residency requirements justify the operational overhead.

What we never do: treat multi-tenancy as a concern that can be added later. The tenant_id is a first-class element of the schema from migration 001. If it's not there at the start, adding it correctly is a full data layer refactor.

Observability: what to instrument before you have load

The time to add observability is before you have load, because after you have load is when you need it most and have the least time to add it correctly.

The minimum viable observability stack for a Series A-stage B2B product:

Structured logging. Every log line is a JSON object with: request_id, user_id, tenant_id, duration_ms, status_code, and the business context (what operation was this?). Unstructured log lines are unsearchable at scale. Structured logs let you answer "show me every request by Tenant X in the last hour that took over 2 seconds" in a single query.

Distributed tracing. One trace ID propagated through every service call, background job, and database query for a given user action. When a user reports "the dashboard is slow," you can pull the trace ID from their request and see exactly which layer added the latency. OpenTelemetry is the standard; the backend (Datadog, Honeycomb, Jaeger) is a configuration decision.

Business metrics as first-class instrumentation. Not just technical metrics (latency, error rate, throughput) — business metrics: tenant.created, subscription.upgraded, feature.used, report.exported. These are the metrics that matter to the Series B conversation, and they should be instrumented at the moment of the business event, not derived from database queries after the fact.

Error budgets and alerting. Define SLOs before launch: "95th percentile API latency under 500ms, error rate below 0.5%." Set alerts at 80% of error budget consumed. Alerting on raw error counts produces alert fatigue; alerting on budget burn rates produces actionable signals.

Deployment: not an afterthought

Deployment architecture decisions affect shipping velocity every day for the life of the product. The decisions that compound badly when made last:

Infrastructure as code from day one. Terraform, Pulumi, or CDK. Not because you'll need to provision 50 environments immediately, but because "we manually configured this in the AWS console" is a phrase that triggers immediate dread in every engineer who inherits the codebase 12 months later.

Environment parity. Dev, staging, and production should be structurally identical. Bugs that appear in staging but not in dev, or in production but not in staging, are almost always environment parity failures. The most common: different environment variables, different database configurations, different secrets management.

Database migration strategy. Every schema change is a migration script. Migrations are run in CI before deployment, on a staging environment that mirrors production data volume, with rollback scripts written alongside. A migration that takes 30 seconds on dev takes 45 minutes on a 50M-row production table. You find out in staging, not production.

Zero-downtime deployments. Blue-green or rolling, with health check gates. Not relevant for a product with 50 users. Increasingly relevant at 5,000 users. The right time to implement it is before the "we deployed and the site went down for 4 minutes" incident, not after.

The cheap version and where it breaks

Every decision above has a fast version and a correct version. The fast version works until it doesn't, and the failure point is usually at the worst possible time.

The UI-first schema breaks when you need to add a new entity relationship that the original data model didn't anticipate, and you discover that your primary keys are wrong for the new model.

The custom auth implementation breaks at the moment a security researcher or a hostile user probes for session management vulnerabilities.

The missing tenant_id breaks at the moment you have your second enterprise customer and they ask for a data isolation demonstration.

The observability gap breaks the first time you get a production incident and spend three hours reading log lines manually to understand what happened.

None of these are hypothetical. They're the events that define whether a Series B raise is a story about momentum or a story about dealing with technical debt.

What fixed looks like

A B2B SaaS at Series B stage with a well-built foundation looks like this: the engineering team is shipping features, not managing infrastructure fires. The database schema accommodates new product requirements without full-table migrations. Adding a new enterprise customer with their own SSO configuration is a half-day task, not a sprint. When a production incident happens, the root cause is identified in under 20 minutes from structured traces. The deployment pipeline is automated, tested, and takes 8 minutes from merge to production.

The architecture conversation in due diligence is a demonstration, not an apology.

This is for you if

You're a founder or CTO building a B2B SaaS platform with real enterprise customers in the pipeline. Pre-seed through Series A. You're past the "does this work at all" validation phase and you're building the thing that needs to work for the next 5 years and 500 enterprise customers. The build scope for a production-grade B2B SaaS platform — data model, auth, multi-tenancy, observability, deployment infrastructure — runs $50k on the lean end for a focused MVP scope to $200k+ for a full-featured platform with enterprise compliance requirements.

This is not for you if you haven't validated the core product hypothesis yet. Build the smallest thing that validates the concept, then invest in production architecture when you know what you're scaling.