This project is a SaaS web application built with SvelteKit, showcasing a multi-tenancy implementation using Turso for database management and Cloudflare for hosting and domain management.
Demo : https://miloudi-mutli-tenancy.software/
- Multi-tenancy with one database per tenant using Turso Multi-DB Schemas
- Subdomain per tenant, achieved by wildcard subdomain and SvelteKit hooks
- Custom tenant domain with auto SSL using Cloudflare for SaaS
- Tenants can download their entire database dump. Reference
- Deployed on Cloudflare Workers
Before you begin, ensure you have the following:
- Node.js and pnpm installed.
- Turso CLI installed. Docs.
- An apex domain connected to Cloudflare.
For development copy .env.example
to .env
, For build and production, export the environment variables to the build environment. If that's Cloudflare Workers, add them to build environment.
TURSO_PLATFORM_AUTH_TOKEN=
TURSO_GROUP_AUTH_TOKEN=
TURSO_CENTRAL_DATABASE_URL=libsql://<db-name>-<org-name>.turso.io
TURSO_SCHEMA_DATABASE_NAME=
TURSO_ORGANIZATION_NAME=
TURSO_GROUP_NAME=default
CLOUDFLARE_ZONE_ID=
CLOUDFLARE_TOKEN=
PUBLIC_DOMAIN=localhost:5173
TURSO_PLATFORM_AUTH_TOKEN
: Runturso auth api-tokens mint <api-token-name>
. This token allows you to create new databases for tenants.TURSO_GROUP_AUTH_TOKEN
: Runturso group tokens create
. This token allows you to access all the databases inTURSO_GROUP_NAME
.TURSO_CENTRAL_DATABASE_URL
: Create a central database in Turso and use the provided URL, Commandturso db create <db-name>
. This database manages all the tenants including their domains and subdomains. This is where you would track usage for subscription and allow/disallow/limit features if this were a SaaS.TURSO_SCHEMA_DATABASE_NAME
: Create a database with the schema flag in Turso, Command :turso db create <db-name> --type schema
.This database will not have any rows, but it's used to synchronize the tenants db. docsTURSO_ORGANIZATION_NAME
: Runturso org list
and use the slug of your organization.TURSO_GROUP_NAME
: Default is "default".CLOUDFLARE_ZONE_ID
: After having added your domain to cloudflare. Go to Cloudflare Dashboard -> Websites -> (your domain) -> you can find the Zone ID in the right sidebar.CLOUDFLARE_TOKEN
: Generate a token with access to your zone with permissionSSL and Certificates:Edit
. This is used to manage custom tenant domains.PUBLIC_DOMAIN
: Uselocalhost:5173
for local development, change to your domain in production. Note: If you don't put the right PUBLIC_DOMAIN you won't be able to access your app normally because the right domain will be treated as a custom tenant domain which probably does not exist.
-
Clone the repository:
git clone https://github.com/ricin9/sveltekit-multi-tenancy
-
Navigate to the project directory:
cd sveltekit-multi-tenancy
-
Install dependencies:
pnpm install
-
Set up your environment variables as described above.
-
Migrate your central and schema databases
pnpm db:central migrate pnpm db:tenant migrate
-
Run the development server:
pnpm run dev
To deploy your SvelteKit app to Cloudflare Workers, follow these steps:
-
Create a Cloudflare Workers project:
- Log in to your Cloudflare dashboard
- Navigate to "Workers & Pages"
- Click "Create application" and follow the prompts to set up your project
-
Add environment variables to build environment:
- In your Cloudflare Workers project settings, go to the "Settings" tab
- Scroll down to "Environment Variables"
- Add all the environment variables from your
.env
file - Note: Do not add environment variables to production or preview environment, instead add them to Build environment. This step is crucial because we're using Sveltekit static env which embeds envars as strings directly in build step.
-
Modify Worker routes: Assuming your domain is
example.com
, add the following routes:example.com
*.example.com
*/*
(This route is for custom domains added through Cloudflare for SaaS)
To add these routes:
- Go to your Cloudflare dashboard -> Workers -> Your Worker -> Settings -> Domains & Routes
- For the first two domains select Custom Domain, for
*/*
select Routes, for the zone select yourPUBLIC_DOMAIN
.
-
Enable Custom Hostname SSL:
- In your Cloudflare site's SSL/TLS settings, go to the "Custom Hostnames" tab
- Ensure that "Cloudflare For SaaS" is enabled. Docs
-
Deploy your application:
- Manual Deployment.
- Run
wrangler deploy
.
- Automatic Deployment.
- If you're using Worker Git integration (added very recently as of writing of this readme), just push to your remote git repo and it will be pulled down and built automatically.
Remember to update your PUBLIC_DOMAIN
environment variable to your production domain when deploying.
As of the date of writing this readme, there is no way to add wildcard subdomain to pages *.example.com
, and you cannot add */*
route so that custom tenant domains are routes automatically to your worker.
You can use Cloudflare Pages, but you would have to add each created subdomain and custom tenant domain either manually or by using the Cloudflare API. I prefer automatically for this demo this is why I used Cloudflare Workers instead.
There are two methods: HTTP and TXT, (Source), HTTP is the fastest one as it only required the tenant to point their domain towards your PUBLIC_DOMAIN
with CNAME dns record after having added it through the tenant settings in the web app and the domain ssl will be installed automatically and will be routed to your app.
It is not required unless you do not have the Entreprise plan. Because of you were to set PUBLIC_DOMAIN
to sub.example.com
, Cloudflare will not install SSL Certificates for 3rd layer *.sub.example.com
unless you are on Entreprise Plan
. So it's just easier using an apex domain.
Yes you can deploy this anywhere, Cloudflare for SaaS would still work, but you will have to configure your proxy to route the wildcard subdomain of your apex, and the custom tenant domains to your application. You can therefore skip all steps of Deployment to Cloudflare Workers
except for the activation of Cloudflare For SaaS
step.
Contributions are welcome! Please feel free to submit a Pull Request.