Skip to content

Operations

Partitioning guidance

When and how to partition the go-sequent event store inside the shared-schema, tenant_id model: partition_key, triggers, recommended steps, optional RLS and the example SQL.

Partitioning guidance

Model: one shared schema with tenant_id columns and hooks. It is not schema-per-tenant and not database-per-tenant.

Physical partitioning is optional and stays inside that shared schema. The migrations create non-partitioned tables. The SQL in the repository under docs/ops/sql/ is guidance only. Apply it deliberately, after a capacity review. store.Migrate and go-sequent migrate never run it.

When to partition

Symptom Candidate
events is far beyond tens of GB, or vacuum is hot Partition by partition_key, often tenant_id or tenant_id:shard
Very large commands Range partition by time, or hash by id
Cross-tenant scans are rare Prefer prune-friendly keys that match your load filters

go-sequent already stores events.partition_key and aggregates.events_partition_key. Set the partition key from tenancy.PartitionKey or tenancy.PartitionKeyHashed:

key := tenancy.PartitionKey(tenantID) // tenantID is a uuid.UUID
// or, to spread one large tenant over several buckets, add a shard string:
hashed := tenancy.PartitionKeyHashed(tenantID, shard)

See Tenancy for the other helpers.

  1. Keep logical multi-tenancy through tenant_id on commands, events, aggregates and projections.
  2. Set partition_key to tenant_id, or to tenant plus a hash, for stream locality.
  3. If needed, convert events into a partitioned parent. Use one partition per tenant hash bucket, or one per tenant for very large tenants.
  4. aggregate_unique_keys stays global within the schema. Include the tenant in unique-key scopes with tenancy.UniqueScope.
  5. Do not create per-tenant schemas as the product model.

Row Level Security

Row Level Security on tenant_id is optional and adds depth. Keep enforcing the tenant match in the repository and on load as well. See Tenancy.

Interaction with HA and backups

  • Partition pruning helps the primary and the replicas. Rebuild workers should filter by partition ranges.
  • Backups remain cluster-level. See Backup and restore.

Example SQL

The file docs/ops/sql/events_partition_by_tenant_hash.example.sql in the repository is an illustration of hash partitioning by tenant. It is not applied automatically.

Docs track the go-sequent library. When APIs drift, the source wins.