Multi-store
Several storefronts, one catalogue
Channels are storefronts over one catalogue, differing in what is published to each and at what price. A store that never creates a second channel pays nothing for the feature: one channel is the default, and every request that names none is served from it.
- core/channels.go channels, publishing
- core/pricing.go per-channel price lists
- 1 default channel, enforced by the database
- platform/ many stores, one install
Need separate stores, not separate storefronts? See many stores from one install.
What a channel scopes
- Publishing. Each product carries the list of channels it is published to;
Publish(product, channels)sets it. - Price. A price list can be limited to one channel, so the same variant sells at a different price on a different storefront — resolved by
PriceInChannel. - The default. Exactly one channel is default, guaranteed by a partial unique index, and is what a request without a channel gets.
- Not orders, customers or stock. Those are one store’s. A second storefront sells the same inventory from the same locations.
Channel: code, name, active, default, products
Storefront A
channel: retail
published set A · retail prices
GoCommerce
one catalogue, one admin, one stock
published set B · outlet prices
Storefront B
channel: outlet
Three things channels are good for
An outlet store
Publish the discontinued lines to a second channel with a lower price list. Stock is shared, so selling out on one side sells out on the other, which is the truth.
A brand per storefront
Two brands, one warehouse, one admin. Each product goes to its brand’s channel; staff and rights are shared because the merchant is.
A wholesale storefront
A B2B channel with a group-restricted price list — how B2B pricing resolves — beside the retail one, on the same catalogue.
Many stores from one install
Platform mode, since GoCommerce 1.1. Run gocommerce platform and one process serves many stores. Each one is a whole store, not a storefront.
| What | How it works |
|---|---|
| A store of its own | Each store gets its own database schema, operators, admin panel, media and modules. |
| Its own address | <slug>.your-domain, or any custom domain you attach. Your proxy asks the platform before issuing a certificate. |
| One shared API host | Or name the store in an X-Store header. |
| A platform API | Create, rename, suspend, resume and delete stores, attach domains, add owners and replace a store’s token. Its credentials open no store. |
| A console | The same actions on screens, on the platform’s own address. New in 1.2. |
| Reports that stay home | A store’s custom SQL reports run as its own read-only login, so they cannot read another store. |
| One Compose file | docker-compose.platform.yml starts the platform with every module installed. |
Planned: one engine for every store
Designed, not built yet. Platform mode and the single-store engine become one thing: every GoCommerce install serves as many stores as it holds, and you move between them from the admin. Read the plan.
| Today | Planned |
|---|---|
| Two ways to run | One. gocommerce serve runs every store; gocommerce platform and its Compose file go away. |
| A schema per store | One set of tables. Every row carries its store, and PostgreSQL row security hides other stores’ rows even from a query that forgets to filter. |
| A sign-in per store | One sign-in. A person belongs to any number of stores, with a role in each. |
| A store per address | A store switcher at the foot of the admin sidebar. Switching keeps your place: from Orders you land on the new store’s Orders. |
| Codes unique per install | Unique per store: two stores can both sell SKU TEE-01, and each numbers its orders from GC-000001. |
| A single-store install | Upgrades in place as store #1. No ids change, and existing clients send nothing new. |
Where the edge is
Channels are one merchant’s
A channel shares the store’s catalogue, staff and books. Unrelated stores belong in platform mode, each in a schema of its own.
No per-channel staff or ledger
Rights, customers, orders and payouts are store-wide. A channel is a shop window, not a subsidiary.
The storefront side is yours
A channel is named on the request, so a second storefront is a second client of the API — anything HTTP. Svelte Commerce’s early connector (0.16.0) names one with PUBLIC_GOCOMMERCE_CHANNEL; without it, the storefront is served from the default channel.
FAQ
Questions about multi-store
What is a channel?
A named storefront over the one catalogue: a code, a name, an active flag and a count of the products published to it. Exactly one channel is the default — enforced by a partial unique index — and a request that names no channel is served from it, which is why a store that never creates a second channel never notices the feature.
What differs between channels?
Two things: which products are published to each, set per product with a list of channel ids, and which price lists apply, since a price list can be limited to one channel. Orders, customers and inventory are not partitioned by channel; a second storefront sells from the same stock.
How does a storefront pick its channel?
By naming it on the request. Any HTTP client can, so a Next.js site and a native app can each be a channel of the same backend, and the admin sees all of them. Svelte Commerce’s early GoCommerce connector, 0.16.0, names one with PUBLIC_GOCOMMERCE_CHANNEL; without it, the storefront is served from the default channel.
Can I run separate brands from one install?
Yes, two ways. Brands that share a catalogue, staff and books are channels of one store: publish each product to its brand’s channel and price it per channel. Brands or merchants that need their own staff, customers, orders and books are separate stores in platform mode, still one install and one database.
Is GoCommerce multi-tenant?
Yes, since GoCommerce 1.1. Run gocommerce platform and one process and one PostgreSQL database serve many stores. Each store lives in a schema of its own, with its own operators, admin panel, media, modules and domains. Channels are a different thing: storefronts of one merchant.
Is platform mode changing?
Yes, by design and not yet in a release. The plan merges platform mode into the ordinary engine: one set of tables where every row carries its store, PostgreSQL row security as the safety net, one sign-in across stores, and a store switcher in the admin. A single-store install upgrades in place. Installs running platform mode today will not be converted automatically; the release notes will say how to move.
How are stores kept apart in platform mode?
By the database, not by a store_id column. Each store is an unchanged engine in its own PostgreSQL schema, so its queries cannot see another store’s tables. Custom SQL reports go further: each store runs them as its own read-only database login, which PostgreSQL refuses anything outside that store’s schema.
How does a request find its store?
By its address: <slug>.<your base domain>, or any custom domain attached to the store. A shared API host can name the store in an X-Store header instead.
One catalogue, as many windows as you need
Create a channel in the admin, publish a product to it, and price a cart against it from the API docs. Or start gocommerce platform and create stores from its console.