Skip to content

👫️ Multitenancy

Event Sourcery implements multitenancy by adding tenant id to all objects it stores.

By default, EventStore works in so-called default context, tenant-less.

Switching tenant

To switch context to specific tenant, one should call scoped_for_tenant method:

scoped_event_store = event_store.scoped_for_tenant("tenant123")

Isolation rules

There are three rules regarding isolation:

  1. streams and events from default, tenant-less context are not visible in any tenant-aware context
  2. streams and events from another tenant are not visible when working with tenant-aware context
  3. streams and events from any tenant are not visible when working with tenant-less, default context

This table summarises visibility rules:

visible? tenant-less tenant A tenant B
tenant-less yes no no
tenant A no yes no
tenant B no no yes

Multitenancy in other features

Outbox and subscriptions

Both Outbox and Subscriptions are meant to be used in a system context, for example to implement a projection of events onto a read model. However, you can always get tenant id when working with them.

On any Recorded instance there is an attribute called tenant_id.

For events that were created in a default, tenant-less context, tenant_id has value of event_sourcery.event_store.DEFAULT_TENANT.

Value of this constant should not be relied upon and is considered an implementation details.

In all places where you wish to check if an event was created in a default context, you should use this constant:

from event_sourcery.event_store import DEFAULT_TENANT


...


for recorded_event in subscription:
    if recorded_event is None:
        break
    elif recorded_event.tenant_id == DEFAULT_TENANT:
        print(f"Got tenant-less event! {recorded_event}")
    else:
        ...

Event Sourcing

In case of Event Sourcing, whenever you construct a Repository make sure you pass a scoped EventStore instance:

scoped_event_store = event_store.scoped_for_tenant("tenant123")

repository = Repository[ExampleAggregate](scoped_event_store)