Architecture
An OpenShop deployment has two long-running processes backed by one PostgreSQL database:
┌──────────────────────────────────────────────────┐│ Shopify admin / webhooks / proxies │└────────────────────────┬─────────────────────────┘ │ v┌──────────────────────────────────────────────────┐│ web process (`openshop start`) ││ - OAuth and session authentication ││ - embedded admin UI and Admin API ││ - webhook, proxy, Function, and MCP routes ││ - cron scheduler │└────────────────────────┬─────────────────────────┘ │ inserts pending flow runs v┌──────────────────────────────────────────────────┐│ PostgreSQL ││ - installations and encrypted tokens ││ - provider configuration ││ - flow runs, checkpoints, and logs ││ - cron overrides and MCP audit data │└──────────────────────────────────────────────────┘ ^ │ leases and executes runs │┌────────────────────────┴─────────────────────────┐│ worker process (`openshop worker`) ││ - provider connectors ││ - Shopify Admin GraphQL ││ - checkpointed steps and retries │└──────────────────────────────────────────────────┘The web and worker processes use the same built openshop.config.ts and
DATABASE_URL. The web process does not execute flows. A deployment therefore
needs at least one instance of each process.
Request lifecycle
Section titled “Request lifecycle”- Shopify launches the embedded app or calls an authenticated route.
- OpenShop resolves the Shopify app and shop identity.
- A cron, API request, webhook, or application service dispatches a flow.
- The run is stored as
pending; a worker leases it whenavailableAtis due. - Each
step()writes a checkpoint. A retry reuses completed step output. - The run ends as
completed,failed, orcanceled; logs remain queryable.
Identity and tenancy
Section titled “Identity and tenancy”Shop-scoped framework data is identified by (appHandle, shop). In single-app
mode, appHandle is default. Multi-app deployments use the key declared under
shopify.apps. This boundary applies to installations, flow runs, provider
configuration, cron overrides, Functions, and MCP tokens.
Application tables created with defineModel() include a shop column by
default, but application code is responsible for applying the correct shop
filter to its own queries.
Scaling boundaries
Section titled “Scaling boundaries”- Run one scheduler unless duplicate cron attempts are acceptable. The scheduler has no leader election. Flow concurrency can reject an overlapping run, but it is not a scheduler de-duplication guarantee.
- Run multiple workers against the same database to increase throughput.
- Set worker concurrency below the combined PostgreSQL and provider capacity.
- Keep migrations separate from process startup so every replica sees the same schema before it begins serving traffic.
See Deploy to production and Operate an app for process and recovery procedures.