OutsourcingVN is operated by Netbase JSC. Planning the SaaS workflow itself, the tenant, role, plan and release states a product needs on any stack, is the SaaS product development solution's question, and whether Laravel is the right framework is the platform page's; this guide plans the Laravel-specific build once both are settled, as multi-tenancy defines the architecture in general.
Contents
- How do tenants, the application and billing fit together?
- How should the first release be built?
- Worked scenario: a vertical SaaS product's first ten tenants
- What has Netbase built on Laravel for a multi-tenant SaaS?
- Where does AI fit in a Laravel SaaS product?
- What should you check before committing to the stack?
- What goes wrong in a Laravel SaaS build?
- Which questions should you ask a Laravel SaaS supplier?
- How this guide is sourced and where it stops
- Common questions
- Plan your Laravel SaaS product
How do tenants, the application and billing fit together?
A tenant signs up, is identified on every request, and is scoped behind authentication before anything it owns is touched; a plan and a billing provider's events decide what that tenant may do, separately from the queued and scheduled work the application runs on its behalf.
| Record | Owned by | Why |
|---|---|---|
| Tenant identification | A domain or subdomain resolver | Every request is matched to one tenant before any query runs |
| Data isolation | One shared database, or a database per tenant | A shared database scopes every query by a tenant column; a dedicated database isolates a tenant's rows entirely |
| Authentication and sessions | Laravel Sanctum | A token or a cookie-based session identifies the user, then the tenant resolver scopes what they can reach |
| Plan and billing state | The application, reacting to a billing provider's webhooks | The payment provider holds card and invoice data; the application still has to know whether a tenant is active, past due or cancelled |
| Queues and scheduled jobs | Laravel's queue and scheduler, routed per tenant | A per-tenant job must not run against, or block, another tenant's data |
Identifying a tenant by domain or subdomain is the first request-level decision; everything else, from the database connection a request uses to the plan it is billed against, is resolved once that match is made.
(opens the full-size diagram in a new tab)
How should the first release be built?
-
Resolve the tenant on every request
A subdomain or a custom domain maps to one tenant before a controller runs, and every later decision depends on that match being correct.
-
Choose the isolation model per module, not once for the whole product
A shared database with a tenant column suits most modules; a dedicated database suits a tenant with its own compliance requirement.
-
Wire authentication with Sanctum
, issuing a token for a third-party or mobile client and a cookie-based session for the product's own single-page front end, as Sanctum's own documentation separates the two.
-
Model plan and billing state as the application's own data
, reacting to a billing provider's webhooks rather than asking the provider what state a tenant is in in real time.
-
Route queues and scheduled jobs per tenant
A notification job or a nightly report runs against one tenant's data and must not block, or leak into, another's.
-
Run migrations against every tenant database that needs the change
, using a specific connection where the schema is per tenant rather than shared.
-
Rehearse onboarding and offboarding
Provision a tenant end to end, then export and remove one, before the first real customer signs up.
Worked scenario: a vertical SaaS product's first ten tenants
A hypothetical scheduling product for clinics onboards its first ten tenant organisations before opening sign-up publicly.
- Milestone one resolves each clinic to its own subdomain and scopes every query by a tenant column in a shared database, since none of the first ten has a dedicated compliance requirement yet.
- Milestone two wires Sanctum so the product's own web app authenticates by session while a companion mobile app authenticates by token, and configures a billing provider's webhooks to drive the application's own trial, active and past-due states.
- Milestone three schedules a per-tenant daily appointment-reminder job and a weekly usage report, each routed so one clinic's job queue never delays another's.
If an eleventh clinic later needs its own database for its own compliance reasons, that tenant moves to a dedicated connection while the other ten stay on the shared one, since the isolation choice is made per tenant rather than fixed for the whole product.
What has Netbase built on Laravel for a multi-tenant SaaS?
Since 2020, Netbase has worked as offshore development and managing partner on a multi-tenant cloud ERP SaaS for a US client that is not named. Phase one, from 2020 to 2023 and aimed at agency SMEs, covers CRM, real-time messaging, HR, a knowledge base, custom fields and workflows, work and project management, and API integrations; see the cloud ERP record. The stack on that record includes React and Next.js, Laravel and Strapi, PostgreSQL, MySQL, MariaDB and MongoDB on AWS. A multi-vendor marketplace whose Laravel API also serves a buyer's mobile app is a different shape, planned on the Laravel marketplace development guide.
Plan the next step for your project
Where does AI fit in a Laravel SaaS product?
The categories that pay off first in a multi-tenant product are support triage that routes an inbound ticket to the right queue, drafting help-centre answers from the product's own documentation for a person to approve, and classifying inbound tenant requests before a human reads them. Tenant data used for an AI feature still has to respect the same isolation rules as everything else in the product. Custom product engineering scopes where an AI feature belongs against where a plan rule or a role check already does the job.
What should you check before committing to the stack?
Laravel's own release notes state that Laravel 13 requires PHP 8.3 as its minimum version, a floor raised from Laravel 12's PHP 8.2, with bug fixes provided for 18 months and security fixes for 2 years on every release. Its Sanctum documentation separates two authentication modes: a long-lived personal access token, sent as a Bearer value in the Authorization header, for a third-party or mobile client, and cookie-based session authentication, protected by CSRF, for a first-party single-page front end; tokens never expire by default but can be given an expiration and pruned with the included Artisan command. Cashier, Laravel's own billing package, handles subscriptions, plan changes, trial periods, coupons and promotion codes, usage-based billing, subscription taxes, invoicing and a billing portal against Stripe's API, so plan rules stay the operator's own configuration rather than hardcoded values. Its scheduler documentation describes a single cron entry driving every scheduled task, defined in code and run per minute, hour, day or custom cron expression, with a lock available to keep a job from running on more than one server. Its migration documentation describes the connection property that targets a specific database connection, the mechanism a per-tenant database migration uses instead of the application's default connection. A tenancy package such as spatie/laravel-multitenancy, described in its own documentation as an unopinionated package providing the bare essentials for both single-database and multiple-database multi-tenancy, is one way to carry these decisions rather than building the resolver and connection-switching logic from nothing. Confirm before scoping a build:
- Which PHP version the target Laravel release requires, since the floor has moved release to release and an older tutorial may understate it.
- Which authentication mode each client needs: a Sanctum token for a mobile or third-party client, or a cookie-based session for the product's own front end.
- Which isolation model each module needs, since a tenant column and a dedicated database can coexist in one product.
- Which queue connection and schedule each per-tenant job runs on, so one tenant's workload cannot block another's.
What goes wrong in a Laravel SaaS build?
- Tenant scoping treated as a query-by-query habit rather than a rule. A missed
where tenant_idclause anywhere in the codebase is a cross-tenant data leak waiting to happen. - Plan state read from the billing provider on every request. The application should hold its own trial, active, past-due and cancelled states, updated by the provider's webhooks, not query the provider live on every page load.
- A scheduled job written for one tenant, then run globally. Without an explicit per-tenant loop, a nightly job runs once against whichever connection or tenant context is current, and the other tenants are skipped.
- Migrations run once and assumed to reach every tenant database. A per-tenant schema needs the migration run against each tenant's own connection, not just the application's default one.
Which questions should you ask a Laravel SaaS supplier?
- How is a tenant identified on every request, and where does that resolution happen in the request lifecycle?
- Which modules need a dedicated database per tenant, and which can share one with a tenant column?
- How does the application's own plan state stay in sync with the billing provider's events?
- How are per-tenant queued and scheduled jobs isolated from each other?
- How is scope fixed? Most Netbase projects are agreed as fixed-scope contracts after discovery, with milestone-based arrangements also available.
How this guide is sourced and where it stops
The Laravel, Sanctum, Cashier, scheduler and migration facts are read from Laravel's own documentation, and the tenancy package facts from its own documentation, on the dates cited. Netbase's delivery lifecycle: discovery and strategic alignment; team assembly and architecture planning; agile execution with outcome-based milestones; modular components; training and rollout; ongoing support. The build sequence and the worked scenario are editorial planning guidance.
Common questions
No. A shared database with a tenant column on every row is the common default; a dedicated database suits a tenant with its own compliance requirement, and the two can coexist in one product.
Cashier, against Stripe's API, covering subscriptions, plan changes, trials, coupons, usage-based billing, tax and invoicing, so plan rules stay configuration rather than code.
Sanctum issues a long-lived token for a mobile or third-party client and uses a cookie-based session, protected by CSRF, for the product's own first-party front end.
Yes, by routing each tenant's queued work to its own queue or connection and looping scheduled jobs per tenant rather than running one global job.
The multi-tenant cloud ERP record, described above in the chapter on what Netbase has built on Laravel for a multi-tenant SaaS.
Plan your Laravel SaaS product
Bring your tenant count, your isolation requirements per module and your billing provider to a brief. Custom product engineering scopes the build, and the SaaS product discovery questions set out what to prepare before it starts; a team still deciding whether to build at all starts with custom build versus SaaS instead.
OutsourcingVN is Netbase's own outsourcing-services platform. Submit a project with your tenant model and billing provider, and a person will reply with the fit.
Related services and solutions
Custom product engineering for a bounded release outcome
One defined release of your product, built to named outcomes and handed over with acceptance evidence.
Learn More