SymorvaDocs
Architecture

Community deployment

The components and data stores that run in, and belong to, the operator's environment, and how they are initialised and upgraded.

A community deployment is everything that holds community data. It runs in the operator's environment — the operator's cloud account or servers in self-hosted mode, or infrastructure the Symorva team runs on the operator's behalf in managed mode. In both modes the data stores, domain and signing identities belong to the operator.

Components

symorva plan lists the owned components for a manifest. Three are always present; each enabled module adds one more.

Component idSourceResponsibility
community-servercoreAccounts, identity, community structure, roles and module host
admin-consolecoreOperator console for members, content, modules and settings
data-storescoreRelational database, cache, object storage and message queue, owned by the operator
messaging-servicechatMessage routing, sync, groups, tribes and membership
meeting-servicemeetingsRoom lifecycle, scheduling, permissions and invitations; media flows through the shared real-time media service
studio-serviceaiStudioProjects, prompts, generated assets and publishing rules; inference runs on the shared AI service
wallet-servicewalletBalances, transfers, payment records and benefit rules; sensitive key operations run inside a trusted execution environment (module design, in preview)
directory-servicedappsListings, categories, allowlists and partner configuration managed by the operator
rewards-servicecreatorEconomyAttribution graph, revenue-share rules and payout records; settles through the wallet module

The source field in the JSON plan tells you which module brought a component, so infrastructure tooling can provision exactly what a manifest needs.

Community server

The community server is the module host. It owns accounts and sessions, device management (including forced sign-out), community structure, roles, and the feature switches that turn module capabilities on and off per community. It exposes the operator-facing Server API and emits webhooks.

Messaging service

The messaging service is built on a self-hosted messaging core that handles connections, sync, conversations and groups, with the community server enforcing business policy through before-send and after-send callbacks. Callbacks are verified, stored idempotently and retried with leases; failures go to a dead-letter store rather than being dropped. This is the arrangement the reference deployment runs today.

Admin console

The admin console is a web application backed by its own management API. In the reference deployment it covers member management and restrictions, reports, content-policy rules, announcements, legal documents, app update policy, feature switches, official sticker packs, DApp listings, meeting packages, withdrawal review, and operator audit logs. Console access is role-based; every permission key is registered by a managed migration, so a new database has a complete permission catalogue from its first start.

Data stores

StoreHolds
Relational databaseAccounts, community structure, roles, module records, payment records and ledgers
CacheSessions, rate limits, short-lived projections
Object storageMedia and file attachments, recordings, generated assets
Message queueOutbox events, asynchronous jobs, webhook delivery
Messaging-core storesMessage log, sync state and group state for the messaging core

The wallet service keeps its custody data in databases separate from the business database, so a compromise of one does not expose the other. See Wallets & assets.

Business events that must reach another system — a notification, a webhook, a push — are written to an outbox in the same transaction as the change that caused them, then delivered asynchronously with retries. A crash between the write and the delivery cannot lose the event.

Initialisation and migrations

Schema changes follow the rules the reference deployment uses for its business and management services:

Load the baseline once. A brand-new database receives its structure from a published baseline through an explicit bootstrap command. Bootstrap refuses to run against a non-empty database.

Run managed migrations on start. Each service image runs its migrations before the service starts. A per-database lock prevents concurrent runners; a ledger records the current version and whether a run was interrupted. If migrations fail, the service does not start.

Refuse newer schemas. A service binary refuses to run against a schema version newer than the one it was built for, so a rollback cannot silently corrupt data written by a newer release.

Migrations are written to be re-runnable: they only add what is missing, never overwrite rows an operator has changed, never edit a migration that has already been released, and never grant roles. Operators therefore receive schema updates by deploying a new release — there is no manual SQL step.

Health and readiness

Every service exposes GET /healthz (the process is alive) and GET /readyz (its dependencies are reachable). Orchestrators should route traffic only to ready instances.

Example layout

A self-hosted deployment is typically kept in the operator's own repository. Real secrets never enter it.

symorva.config.json
stack.env.example

The layout is illustrative. Example files document every variable a service reads; the runtime directory is generated per environment and excluded from version control.

On this page