Skip to main content

Tenancy configuration

[tenancy]​

Named tenants: whether they are served, where their data lives, and how many stay open.
[tenancy]
mode = "enabled"
provisional_tenant_lifetime = "10m"

tenancy.mode​

stringrestart to apply

Whether named tenants are served. With "disabled" only the default tenant exists, and a request naming a tenant in NGSILD-Tenant is answered 501 NoMultiTenantSupport. On by default, so a client can name a tenant without any setup on the broker: the first operation that creates something in a tenant creates the tenant.

Default
"enabled"
Allowed values
"disabled"Turn the feature off.
"enabled"Turn the feature on.
Environment variable
ANDROMEDA__TENANCY__MODE

tenancy.provisional_tenant_lifetime​

non-zero durationrestart to apply

How long a new tenant whose database still holds nothing is kept before its database is dropped. A creating operation that names a tenant for the first time prepares its database before it runs, and the tenant is answered as nonexistent until that database holds information; a refused operation leaves such a tenant behind.

Default
"10m"
Must be
0 < request_limits.timeout < provisional_tenant_lifetime
Environment variable
ANDROMEDA__TENANCY__PROVISIONAL_TENANT_LIFETIME

[tenancy.default_tenant]​

The default tenant's pool.
[tenancy.default_tenant]
max_connections = 32

tenancy.default_tenant.max_connections​

positive integerrestart to apply

The most connections the default tenant's pool opens, in each broker process. Named tenants size theirs with tenancy.databases.max_connections.

Default
32
Must be
0 < max_connections
Environment variable
ANDROMEDA__TENANCY__DEFAULT_TENANT__MAX_CONNECTIONS

[tenancy.databases]​

How each named tenant's database is named and pooled.
[tenancy.databases]
name_prefix = "andromeda_tenant"
max_connections = 4

tenancy.databases.name_prefix​

SQL identifier prefixrestart to apply

The prefix every tenant database name starts with. Maintenance also uses it to recognise databases on the server that look like a tenant's but belong to none. Must match [A-Za-z_][A-Za-z0-9_]*, so the database names need no quoting.

Default
"andromeda_tenant"
Environment variable
ANDROMEDA__TENANCY__DATABASES__NAME_PREFIX

tenancy.databases.max_connections​

positive integerrestart to apply

The most connections each named tenant's pool opens, in each broker process. With tenancy.residency.max_resident it bounds the open connections at their product, plus the default tenant's pool. Behind a proxy, database.pooler.max_connections_per_tenant applies instead.

Default
4
Must be
0 < max_connections
Environment variable
ANDROMEDA__TENANCY__DATABASES__MAX_CONNECTIONS

[tenancy.residency]​

How many tenants stay loaded, and for how long.
[tenancy.residency]
idle_eviction_after = "15m"
max_resident = 16
sweep_interval = "30s"
min_wake_interval = "30s"
woken_lifetime = "1m"
max_wakes_per_pass = 4
max_concurrent_evictions = 8

tenancy.residency.idle_eviction_after​

non-zero durationrestart to apply

How long an unused tenant stays loaded. Unloading a tenant closes its pool and stops its background work.

Default
"15m"
Must be
0 < idle_eviction_after
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__IDLE_EVICTION_AFTER

tenancy.residency.max_resident​

positive integerrestart to apply

The most tenants loaded at once. A tenant with requests in flight is never unloaded, nor is a tenant loaded for due work within tenancy.residency.woken_lifetime, so the count can exceed this until those requests complete and those lifetimes end. Room is made by unloading the least recently used of the other tenants. A tenant with a periodic notification due within tenancy.residency.min_wake_interval is unloaded only when every other candidate has one too. A tenant loaded for a periodic notification takes a place once per timeInterval: while every place is taken, until its notification is sent, and otherwise for tenancy.residency.woken_lifetime. While those shares add up to more places than this leaves beside the default tenant and the tenants requests use, the broker cannot load tenants as fast as their work falls due: their notifications fall behind without bound, and the broker logs a warning and reports the overdue wakes in andromeda_tenant_overdue_wakes.

Default
16
Must be
0 < max_resident
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__MAX_RESIDENT

tenancy.residency.sweep_interval​

non-zero durationrestart to apply

How often idle tenants are unloaded and provisional tenants settled.

Default
"30s"
Must be
0 < sweep_interval
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__SWEEP_INTERVAL

tenancy.residency.min_wake_interval​

non-zero durationrestart to apply

The shortest wait before a tenant that was just unloaded is loaded again for due work, such as an expiry or a periodic notification. A due time sooner than this is pushed back to it, so a tenant that is only a little overdue is not unloaded and reloaded in a loop. A failed check for due work is retried this far out. A tenant with a periodic notification due within this interval is the last to be unloaded to make room. If it is unloaded all the same, that notification can be late by up to this interval, unless the tenants with due work need more places than tenancy.residency.max_resident leaves, as described there.

Default
"30s"
Must be
0 < min_wake_interval
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__MIN_WAKE_INTERVAL

tenancy.residency.woken_lifetime​

non-zero durationrestart to apply

The longest a tenant loaded for its due work keeps its place. Until its due work has run it is not unloaded, not even to make room for another tenant. While every place is taken, it gives up its place as soon as that work has run, so another tenant with due work can be loaded; while places are free, it keeps its place for this whole time. After it, such a tenant is the first to be unloaded again, yet never displaces a tenant a request used.

Default
"1m"
Must be
0 < woken_lifetime < tenancy.residency.idle_eviction_after
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__WOKEN_LIFETIME

tenancy.residency.max_wakes_per_pass​

positive integerrestart to apply

The most unloaded tenants one pass loads: for due work first, then, in what that leaves, for tenants whose extensions are behind the versions the server ships. Woken tenants share tenancy.build.max_concurrent with tenants loaded for requests, so this keeps a burst of wakes from crowding requests out.

Default
4
Must be
0 < max_wakes_per_pass
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__MAX_WAKES_PER_PASS

tenancy.residency.max_concurrent_evictions​

positive integerrestart to apply

The most tenants unloading at once. Loaded and unloading tenants together stay within tenancy.residency.max_resident plus this. A load that must make room while every slot is busy waits for one within tenancy.build.admission_timeout.

Default
8
Must be
0 < max_concurrent_evictions
Environment variable
ANDROMEDA__TENANCY__RESIDENCY__MAX_CONCURRENT_EVICTIONS

[tenancy.build]​

How a tenant is loaded on its first request.
[tenancy.build]
max_concurrent = 8
admission_timeout = "20s"

tenancy.build.max_concurrent​

positive integerrestart to apply

The most tenants loading at once. Loading opens a pool and, when the tenant's schema is behind or absent, runs migrations over a direct connection. Requests past the bound wait for at most tenancy.build.admission_timeout.

Default
8
Must be
0 < max_concurrent
Environment variable
ANDROMEDA__TENANCY__BUILD__MAX_CONCURRENT

tenancy.build.admission_timeout​

non-zero durationrestart to apply

How long a request may wait for its tenant to load before it is answered 503 with Retry-After. Covers the load itself and every wait ahead of it: another request loading the same tenant, the creation of a new tenant's database, a free loading slot, and a free unloading slot when the cache is full. A tenant still being created or loaded when the time runs out goes on loading, so a retry finds it further along or ready.

Default
"20s"
Must be
0 < admission_timeout < request_limits.timeout
Environment variable
ANDROMEDA__TENANCY__BUILD__ADMISSION_TIMEOUT