Multi-Tenant E-Commerce Architecture with Turso

Jamie BartonJamie Barton
Cover image for Multi-Tenant E-Commerce Architecture with Turso

Complexity often creeps in unnecessarily in eCommerce.

Let’s explore a straightforward approach to building multiple storefronts using a single codebase while maintaining separation of concerns and scalability.

Instead of sharing a database with complex tenant isolation, we instead share a single codebase with the store’s that is powered by themes, and configuration via environment variables.

  1. One template codebase
  2. One Vercel Project per store
  3. One database per store

This architecture provides several advantages:

  • Simple development and maintenance
  • Strong tenant isolation
  • Independent scaling
  • Easier debugging
  • Lower risk of cross-tenant issues

#How does it work?

This architecture is far simpler to work with locally too. One repository is now responsible for many stores, including different themes.

Let’s assume we have a frontend with the following structure:

/template-repo
  ├── src/
  │   ├── components/
  │   ├── app/
  │   └── lib/
  │   └── themes/
  ├── .env.example
  └── package.json

The storefront works differently depending on the environment variables:

STORE_NAME="My Store"
STORE_THEME="default"
DATABASE_URL="libsql://..."
DATABASE_AUTH_TOKEN="..."
STRIPE_SECRET_KEY="..."

These environment variables alter the appearance of the store (with theme and name), the products it sells (with a separate database), and route payments to the right team (with dedicated Stripe accounts).

#Deployment Strategy

Deployments are super easy with this architecture.

For new tenants:

  1. Create a new Vercel project
  2. Connect it to the same repository
  3. Configure tenant-specific environment variables
  4. Deploy

For existing tenants:

  1. Open a Pull Request
  2. Preview changes
  3. Merge & Deploy

#Database Management

Each store gets its own database instance, containing tables for:

  • Products
  • Orders
  • Customers
  • Shopping Carts
  • Inventory

This approach for vendors means:

  • No data mixing between tenants
  • Simpler backup and restore processes
  • Easier troubleshooting

New databases can be created from an existing "seed database", or if you prefer a managed solution — Turso Multi-DB Schemas will automatically propagate changes to all databases when the parent schema is updated.

const database = await turso.databases.create("store-1", {
  group: "default",
  seed: {
    type: “database”,
    name: “template-db”
  }
});

Connecting to each store database is now easier. Name your database after the Vercel Project’s production URL, and it’s made available via an environment variable:

import { createClient } from '@libsql/client';
import slugify from 'slugify';

const storeName = slugify(process.env.VERCEL_PROJECT_PRODUCTION_URL);

export const turso = createClient({
  url: `libsql://${storeName}-org-name.turso.io`,
  authToken: process.env.TURSO_GROUP_AUTH_TOKEN,
});

Using something like Drizzle is also a lot simpler. No need for WHERE tenant = ?!

await db.query.products.findMany();

await db.insert(schema.carts).values({
  items: [
    { product_id: 1, quantity: 2 },
    { product_id: 2, quantity: 1 },
  ],
});

await db
  .update(schema.orders)
  .set({ shipped: true })
  .where(eq(schema.orders.id, id));

Learn more about Drizzle & Turso.

#Continuous Deployment

Most modern deployment platforms provide immutable deployments for each pull request, or commit. Since each store has its own Vercel project that is connected to the repository, Vercel will automatically create a new preview or production deployment every time code is changed.

  1. Push changes to the template repository
  2. Automatic preview deployments for each store
  3. Review and approach changes
  4. Deploy to production stores

#The Cost Per Store

The approach of creating isolated environments per store may traditionally be seen as an expensive route, but measuring costs on a per-store basis is now a lot simpler than before.

#Conclusion

This simple multi-tenant e-commerce architecture offers a pragmatic approach to building and scaling tenant based storefronts. By using a single codebase with customizable themes and configuration, coupled with isolated databases and deployments, we achieve a balance of simplicity and scalability.

While this approach may not suit every use case, it provides a starting point for many platforms looking to build a multi-tenant architecture with low complexity.

A common question is how to aggregate data across all stores to see who are your most active and valuable customers — you can learn how I do that in this article.

scarf