Series MapLesson 40 / 112
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Build CoreOrdered learning track

Multi-Tenancy and Tenant Configuration

Multi Tenancy and Enterprise Configuration

Tenant-aware behavior di sistem enterprise: tenant isolation, routing, data access, logging, tenant-specific catalog/pricing/rules, dan internal verification model

9 min read1619 words
PrevNext
Lesson 40112 lesson track22–61 Build Core
#multi-tenancy#tenant-isolation#configuration#enterprise+5 more

Part 040 — Multi-Tenancy and Enterprise Configuration

Fokus part ini: memahami tenant sebagai boundary teknis, data, security, configuration, observability, dan operations. Dalam sistem enterprise seperti CPQ/quote/order management, tenant-aware behavior dapat menyentuh routing, authorization, catalog, pricing, rules, persistence, cache, event, dan audit.

Multi-tenancy bukan sekadar menambahkan kolom tenant_id.

Multi-tenancy menjawab:

For this request/job/event/data/config/log entry, which tenant does it belong to, who is allowed to access it, and how do we prove isolation?

Dalam konteks CSG Quote & Order, jangan mengasumsikan model tenancy internal. Kita hanya bisa membuat mental model dan verification checklist.


1. Tenant Is a Boundary

Tenant dapat berarti beberapa hal tergantung sistem:

- customer organization
- business unit
- reseller/partner
- market/region
- legal entity
- deployment customer
- logical partition of data and configuration

Yang penting bukan namanya. Yang penting adalah boundary-nya.

Tenant boundary dapat mempengaruhi:

- API access
- database query
- product catalog
- pricing rule
- quote visibility
- order visibility
- workflow rule
- event consumption
- audit log
- integration credentials
- retention policy
- observability labels

Senior rule:

If tenant identity is wrong, everything downstream may be wrong.

2. Multi-Tenancy Is Not Only Security

Security adalah bagian besar, tetapi bukan satu-satunya.

ConcernTenant-aware example
Securityuser can only access tenant A
Data accessSQL filters by tenant
Catalogtenant A sees product set X
Pricingtenant A uses discount policy Y
Workflowtenant A requires approval step
Integrationtenant A sends order to endpoint Z
Observabilitylogs and metrics include tenant context safely
Operationsincident impact can identify affected tenants

Dalam CPQ/order systems, catalog/pricing/rules sering menjadi tenant-aware. Itu membuat tenancy bukan hanya auth concern, tetapi correctness concern.


3. Tenant Resolution

Tenant resolution adalah proses menentukan tenant dari request/job/event.

Possible sources:

- authenticated token claim
- hostname/subdomain
- path segment
- header
- mTLS certificate attribute
- API gateway context
- session/context established upstream
- job parameter
- Kafka event header/body
- database record ownership

Example:

GET /tenants/acme/quotes/Q-123
Host: api.example.com
Authorization: Bearer <token with tenant=acme>
X-Tenant-Id: acme

This request has multiple tenant signals. They must be consistent.

Danger:

Token says tenant=acme
Header says tenant=beta
Path says tenant=gamma

What wins?

There must be a rule.


4. Trusted vs Untrusted Tenant Signals

Not every tenant signal is equally trustworthy.

SourceTrust levelNotes
Verified token claimhighif issuer/audience/key are validated
Gateway-injected headermedium/highonly if direct client cannot spoof it
Raw client headerloweasily spoofed
Path parameterlow/mediummust be authorized against identity
Subdomainmediumdepends on routing and cert model
Database ownershiphigh for existing recordmust be checked before mutation

Bad pattern:

String tenantId = request.getHeaderString("X-Tenant-Id");

If header is accepted directly from client, tenant isolation is broken.

Better:

TenantId tenantId = tenantResolver.resolve(securityContext, requestContext);

And the resolver validates consistency.


5. Tenant Resolution Example

Illustrative code:

public final class TenantResolver {
    public TenantId resolve(SecurityIdentity identity, RequestMetadata request) {
        TenantId tokenTenant = identity.tenantId()
            .orElseThrow(() -> new ForbiddenException("Missing tenant claim"));

        Optional<TenantId> pathTenant = request.pathTenantId();

        if (pathTenant.isPresent() && !pathTenant.get().equals(tokenTenant)) {
            throw new ForbiddenException("Tenant mismatch");
        }

        return tokenTenant;
    }
}

Important:

Tenant mismatch is not a normal validation error.
It is a security-relevant event.

Log carefully:

- do log mismatch category
- do log correlation ID
- do log authenticated subject if allowed
- do not log sensitive token content

6. Tenant Context Lifecycle

Tenant context must be established once and propagated safely.

Typical lifecycle:

HTTP request arrives
-> authentication filter validates identity
-> tenant resolver determines tenant
-> tenant context is attached to request context
-> authorization checks use tenant
-> service layer receives tenant explicitly or via controlled context
-> repository queries include tenant
-> logs/events/audit include tenant safely
-> context is cleared after request

Critical rule:

Tenant context must not leak across requests.

ThreadLocal risk:

public final class TenantContextHolder {
    private static final ThreadLocal<TenantId> CURRENT = new ThreadLocal<>();
}

If not cleared correctly, tenant A request can poison tenant B request on reused thread.

Better patterns:

- pass TenantId explicitly to service/repository methods
- use request-scoped context managed by container
- if ThreadLocal is used, set/clear in strict try/finally
- wrap executor tasks to propagate and clear context

7. Explicit Tenant Parameter vs Implicit Context

Explicit:

quoteService.getQuote(tenantId, quoteId);

Pros:

- visible in code review
- testable
- hard to forget in service boundary

Cons:

- method signatures are longer
- easy to pass wrong tenant if not typed

Implicit:

TenantId tenantId = tenantContext.currentTenant();

Pros:

- less repetitive
- convenient in framework code

Cons:

- hidden dependency
- async propagation risk
- harder to test
- cross-request leak risk

Senior compromise:

Use controlled context at technical boundary, then pass tenant explicitly across business/data boundaries.

8. Tenant-Aware Routing

Tenant-aware routing means tenant affects where request or operation goes.

Examples:

- tenant A uses pricing service cluster A
- tenant B uses regional endpoint B
- tenant C uses legacy adapter
- tenant D has dedicated database
- tenant E has special order integration endpoint

Routing sources:

- tenant config
- environment config
- service discovery
- gateway rule
- feature flag

Failure modes:

- tenant routed to wrong downstream
- stale tenant route after migration
- partial rollout routes only some pods correctly
- fallback route sends data to shared/default tenant

Rule:

No tenant-aware route should silently fall back to another tenant route.

9. Tenant-Aware Data Isolation Models

Common models:

ModelDescriptionProsCons
Database per tenanteach tenant has separate DBstrong isolationhigh operational cost
Schema per tenantsame DB, separate schemamoderate isolationmigration complexity
Shared tables with tenant_idsame tables, tenant columnefficienthighest query discipline risk
Row-level securityDB enforces tenant predicatedefense in depthpolicy complexity
Deployment per tenantseparate app/runtimestrong operational isolationexpensive, version drift

No model is universally best.

For enterprise quote/order systems, trade-off often depends on:

- customer isolation requirement
- data volume
- customization depth
- regulatory requirement
- operational scale
- migration strategy
- reporting/query needs

10. Shared Table with Tenant Column

Common model:

CREATE TABLE quote (
    tenant_id text NOT NULL,
    quote_id text NOT NULL,
    status text NOT NULL,
    created_at timestamptz NOT NULL,
    PRIMARY KEY (tenant_id, quote_id)
);

Good query:

SELECT *
FROM quote
WHERE tenant_id = :tenant_id
  AND quote_id = :quote_id;

Dangerous query:

SELECT *
FROM quote
WHERE quote_id = :quote_id;

Even if quote_id is globally unique today, relying on that may break future tenancy model.

Senior rule:

Tenant predicate should be structurally hard to forget.

11. Tenant-Aware Repository API

Bad:

Optional<QuoteEntity> findById(String quoteId);

Better:

Optional<QuoteEntity> findByTenantAndId(TenantId tenantId, QuoteId quoteId);

Even better with typed IDs:

public record TenantId(String value) {}
public record QuoteId(String value) {}

Repository:

public interface QuoteRepository {
    Optional<QuoteEntity> findById(TenantId tenantId, QuoteId quoteId);
    void save(TenantId tenantId, QuoteEntity quote);
}

Review signal:

If repository method can access business data without TenantId, investigate.

There may be legitimate admin/reporting exceptions, but they must be explicit and audited.


12. Tenant-Aware MyBatis Pattern

Example mapper:

<select id="findQuote" resultMap="QuoteResultMap">
  SELECT tenant_id, quote_id, status, created_at
  FROM quote
  WHERE tenant_id = #{tenantId}
    AND quote_id = #{quoteId}
</select>

Dangerous dynamic SQL:

<where>
  <if test="quoteId != null">
    quote_id = #{quoteId}
  </if>
  <if test="tenantId != null">
    AND tenant_id = #{tenantId}
  </if>
</where>

If tenantId is optional, tenant isolation is optional. That is usually unacceptable.

Better:

tenantId should be required at method signature and SQL level.

13. Row-Level Security as Defense in Depth

PostgreSQL Row-Level Security can enforce tenant predicates at DB level.

Conceptual example:

ALTER TABLE quote ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation_policy
ON quote
USING (tenant_id = current_setting('app.tenant_id'));

Then application sets session variable per transaction:

SET LOCAL app.tenant_id = 'acme';

Benefits:

- protects against missing predicate in some queries
- centralizes isolation policy
- useful for defense in depth

Risks:

- connection pool session contamination if not SET LOCAL / transaction-scoped
- migration complexity
- debugging query behavior requires DB policy knowledge
- bulk/admin jobs need explicit bypass model

Do not assume RLS exists internally. Verify.


14. Tenant-Aware Logging

Logs should support tenant-scoped incident analysis.

Example structured log fields:

{
  "timestamp": "2026-07-10T08:00:00Z",
  "level": "INFO",
  "message": "Quote submitted",
  "tenantId": "acme",
  "quoteId": "Q-123",
  "correlationId": "c-789"
}

But logs also have risk:

- tenant ID may be sensitive in some contexts
- quote/order IDs can be high-cardinality
- customer names may be PII or commercially sensitive
- log aggregation access may be broader than app access

Rule:

Log enough to debug tenant impact, but do not leak tenant-sensitive business data.

15. Tenant-Aware Metrics

Metrics labels with tenant ID are tempting.

http_requests_total{tenant="acme"}

Risk:

- high cardinality
- observability cost explosion
- metric backend instability
- accidental exposure of tenant list

Alternatives:

- use tenant tier/segment instead of tenant ID
- emit tenant ID only in logs/traces with access control
- allow tenant label only for limited curated metrics
- use exemplars/traces for deep investigation

Senior question:

Do we need tenant as metric label, or just as log/trace attribute?

16. Tenant-Specific Configuration

Tenant-specific config may include:

- enabled product catalog
- price book
- discount rules
- tax rules
- approval workflow
- quote expiration policy
- order submission adapter
- integration credentials reference
- feature flags
- rate limits
- data retention rules

This is more than application config. It is business behavior.

Governance required:

- owner
- version
- effective date
- validation
- audit trail
- rollback
- approval process
- test coverage

17. Tenant-Specific Product Catalog

In CPQ-like systems, product catalog may vary by tenant.

Questions:

- which products are visible to tenant?
- which product versions are effective now?
- are bundles tenant-specific?
- are compatibility rules tenant-specific?
- what happens to existing quotes when catalog changes?
- can an in-flight quote use a previous catalog version?

Failure modes:

- tenant sees wrong product
- quote uses catalog version not effective for tenant
- catalog update breaks old quote reprice
- cache key omits tenant/catalog version

Safe pattern:

tenantId + catalogVersion/effectiveDate should be part of catalog lookup context.

18. Tenant-Specific Pricing and Rules

Pricing correctness is sensitive.

Tenant-aware pricing context may include:

- tenant ID
- customer segment
- sales channel
- currency
- price book
- effective date
- promotion eligibility
- tax boundary
- contract terms

Bad pattern:

Price price = pricingService.price(productId);

Better:

Price price = pricingService.price(new PricingContext(
    tenantId,
    productId,
    currency,
    effectiveDate,
    salesChannel,
    customerSegment
));

Review question:

Is pricing context complete and explicit?

19. Tenant-Specific Safe Defaults

Tenant config fallback is dangerous.

Bad:

if tenant-specific price book missing, use default price book

That may produce legally/commercially wrong quote.

Better:

if tenant-specific price book missing, fail closed with controlled business error

Safe default for tenant-specific config should usually be:

no tenant config = cannot perform tenant-specific operation

Exception only if explicitly approved and documented.


20. Tenant-Aware Cache Keys

Cache key must include every dimension affecting result.

Bad:

catalog:product:P100
price:product:P100
quote:Q123

Better:

tenant:acme:catalog:v42:product:P100
tenant:acme:pricebook:pb-2026-07:currency:USD:product:P100
tenant:acme:quote:Q123

But do not blindly put sensitive data in keys if cache is shared/observable.

Cache key checklist:

- tenant ID
- region if behavior differs
- catalog version/effective date
- currency
- rule version
- feature flag variant if result differs

Failure mode:

Cache key missing tenant = cross-tenant data leak.

21. Tenant-Aware Events

Events should carry tenant context intentionally.

Possible fields:

{
  "eventId": "evt-123",
  "eventType": "QuoteSubmitted",
  "tenantId": "acme",
  "quoteId": "Q-123",
  "occurredAt": "2026-07-10T08:00:00Z"
}

Or tenant in Kafka headers:

headers:
  tenant-id: acme
  correlation-id: c-789

Questions:

- is tenant ID part of event body, header, or both?
- can consumers authorize/partition by tenant?
- can replay preserve tenant context?
- is tenant ID required by schema?
- is event topic shared or tenant-specific?

Rule:

Async processing must not lose tenant context.

22. Tenant and Kafka Partitioning

If tenant affects ordering, partition key matters.

Options:

key = tenantId
key = quoteId
key = tenantId + quoteId
key = orderId

Trade-offs:

KeyProsCons
tenantIdtenant-level orderinghot tenant can bottleneck
quoteIdquote-level orderingtenant events spread across partitions
tenantId+quoteIdscoped orderingkey design complexity
orderIdorder lifecycle orderingquote/order correlation may need joins

Do not pick partition key randomly. It encodes ordering and scaling behavior.


23. Tenant-Aware Integration Credentials

Some tenants may have tenant-specific external systems.

Examples:

- tenant-specific order endpoint
- tenant-specific SFTP bucket
- tenant-specific API key reference
- tenant-specific certificate
- tenant-specific webhook target

Credential handling rule:

Tenant config should reference secrets, not contain secret values.

Example:

{
  "tenantId": "acme",
  "orderAdapter": "sap-v2",
  "endpoint": "https://orders.acme.internal",
  "credentialRef": "secret://tenant/acme/order-adapter"
}

Never log resolved secret.


24. Tenant-Aware Authorization

Authorization should consider tenant and resource.

Not enough:

user has role QUOTE_VIEWER

Need:

user has QUOTE_VIEWER permission for tenant acme and quote Q-123 is owned by tenant acme

Authorization flow:

1. authenticate identity
2. resolve tenant
3. verify identity allowed for tenant
4. load resource by tenant + resource ID
5. verify resource belongs to tenant
6. apply operation-specific permission

Avoid:

load quote by quoteId first, then check tenant later

If query is not tenant-scoped, data may leak via timing/error differences.


25. Tenant-Aware Error Handling

Error messages can leak tenant existence.

Example:

Tenant beta does not exist

May reveal tenant names.

Safer external response:

{
  "code": "FORBIDDEN",
  "message": "Access denied"
}

Internal log:

{
  "event": "TENANT_ACCESS_DENIED",
  "requestedTenant": "beta",
  "authenticatedSubject": "user-123",
  "correlationId": "c-789"
}

Access to logs must be controlled.


26. Tenant-Aware Batch and Jobs

Jobs are often where tenant bugs hide.

Examples:

- nightly quote expiration
- catalog sync
- price book refresh
- reconciliation
- cleanup
- archival
- event replay

Questions:

- does job run per tenant or globally?
- how is tenant context established?
- can one tenant failure block all tenants?
- is job idempotent per tenant?
- is progress tracked per tenant?
- is locking per tenant or global?

Bad pattern:

UPDATE quote SET status = 'EXPIRED'
WHERE expires_at < now();

Better for tenant-scoped job:

UPDATE quote
SET status = 'EXPIRED'
WHERE tenant_id = :tenant_id
  AND expires_at < now()
  AND status = 'ACTIVE';

27. Tenant-Aware Reconciliation

Reconciliation jobs compare expected state with actual state.

Tenant-aware reconciliation dimensions:

- tenant
- catalog version
- pricing rule version
- order integration adapter
- event stream offset/window
- external system state

Example:

For tenant acme, find orders submitted locally but missing external acknowledgement after 30 minutes.

This should not accidentally scan or mutate all tenants unless explicitly intended.


28. Tenant-Aware Deployment Models

Possible models:

shared deployment for all tenants
shared deployment by region
dedicated deployment for large tenant
hybrid cloud/on-prem deployment
tenant-specific adapter deployment

Operational questions:

- can one tenant overload shared service?
- is rate limiting tenant-aware?
- can canary target specific tenants?
- can rollback affect only one tenant?
- can support identify impacted tenants quickly?

Feature flags and rollout often become tenant-aware in enterprise systems.


29. Tenant Rate Limiting and Quotas

Rate limits may exist at several levels:

- global service limit
- tenant limit
- user limit
- API client limit
- endpoint-specific limit
- downstream dependency limit

A tenant-aware limiter needs key design.

rate-limit:tenant:acme:endpoint:quote-submit

But high-cardinality metrics must be controlled.

Failure modes:

- one tenant consumes all capacity
- limiter key omits tenant
- limiter bypassed for async jobs
- emergency tenant allowlist has no expiry

30. Tenant-Aware Feature Flags

Feature flag targeting may be:

- all tenants
- tenant allowlist
- tenant segment
- region
- percentage rollout
- user group

Risks:

- flag state differs from config state
- tenant gets feature without required migration
- rollback disables feature but leaves data in new shape
- stale flag remains forever

Rule:

Tenant-targeted feature must be compatible with tenant data, API contract, and operational rollback.

31. Tenant Configuration Versioning

Tenant config should be versioned if it affects business outcome.

Example:

{
  "tenantId": "acme",
  "configVersion": "2026-07-10T08:00:00Z",
  "catalogVersion": "cat-42",
  "priceBookVersion": "pb-2026-07",
  "rulesVersion": "rules-17"
}

Why version matters:

- audit quote calculation
- reproduce historical quote
- debug customer dispute
- roll back pricing rule
- compare tenant behavior before/after rollout

For CPQ/order systems, reproducibility is critical.


32. Tenant-Aware Audit Trail

Audit should answer:

- who changed tenant config?
- what changed?
- when did it change?
- which tenant was affected?
- who approved it?
- what quote/order outcomes used that version?

Audit event example:

{
  "eventType": "TenantPricingRuleChanged",
  "tenantId": "acme",
  "actor": "user-123",
  "oldVersion": "rules-16",
  "newVersion": "rules-17",
  "changedAt": "2026-07-10T08:00:00Z",
  "correlationId": "c-789"
}

Do not treat tenant config changes as simple admin CRUD. They can change commercial outcomes.


33. Tenant Migration

Tenant migration examples:

- move tenant from shared DB to dedicated DB
- move tenant to new catalog model
- migrate tenant to new pricing engine
- move tenant between regions
- change tenant integration adapter

Migration risks:

- dual writes inconsistent
- cache still points to old location
- events published with old routing
- in-flight jobs operate on old config
- rollback impossible after data shape changes

Tenant migration needs:

- migration plan
- compatibility window
- reconciliation
- observability
- rollback/roll-forward decision
- customer impact assessment

34. Failure Modes

Failure modeSymptomRoot causeDetection
Cross-tenant data leakuser sees wrong quote/ordermissing tenant predicateaudit/log/security test
Tenant context lostasync/event/job uses default tenantcontext not propagatedtrace/log with missing tenant
Cache pollutionwrong catalog/price returnedkey omits tenant/versioncache key review
Wrong tenant routingrequest hits wrong downstreamstale route/configconfig version + route logs
Tenant config driftpods behave differentlypartial rollout/reloadconfig hash per pod
Unsafe tenant fallbackdefault catalog/pricing usedmissing config hiddenfail-closed validation
High-cardinality metricsobservability degradedtenant label everywheremetrics cardinality review
Job scans all tenantslarge incident/blast radiusmissing job tenant scopejob dry-run/report
Event lacks tenantconsumer cannot isolateschema/header omissionevent contract test

35. Debugging Tenant Bugs

Start with identity and context.

Checklist:

1. identify correlation ID / trace ID
2. identify authenticated subject
3. identify resolved tenant
4. compare tenant signals: token, path, header, gateway context
5. verify authorization decision
6. verify repository query includes tenant
7. verify cache key includes tenant and version
8. verify event header/body includes tenant
9. verify async/job context propagation
10. verify tenant config version used
11. verify catalog/pricing/rule version used
12. verify logs/audit for mismatch or fallback

Useful incident question:

Is this bug global, tenant-specific, region-specific, or data-version-specific?

That question often reduces search space dramatically.


36. PR Review Checklist

For any tenant-sensitive change:

Tenant resolution:
- where does tenant come from?
- is source trusted?
- are conflicting tenant signals rejected?
- is tenant context cleared after request?

Authorization:
- is identity authorized for tenant?
- is object ownership checked tenant-scoped?
- are negative tests present?

Data access:
- does every query include tenant predicate?
- are repository APIs tenant-explicit?
- are admin/global queries explicit and audited?

Cache:
- does cache key include tenant and version dimensions?
- is invalidation tenant-scoped?

Events:
- does event contain tenant context?
- is tenant required in schema?
- is partition key intentional?

Jobs:
- is job scoped per tenant or intentionally global?
- is progress tracked per tenant?
- is locking tenant-aware?

Config:
- is tenant config versioned?
- is fallback safe?
- is change audited?

Observability:
- are logs tenant-aware and redacted?
- are metrics safe from cardinality explosion?
- can incident impact identify affected tenants?

37. Internal Verification Checklist

For CSG Quote & Order or similar enterprise systems, verify:

Tenancy model:
- what does tenant mean internally?
- is tenant same as customer, account, business unit, region, or something else?
- is service single-tenant, multi-tenant, hybrid, or deployment-per-customer?
- where is tenant identity resolved?

API and security:
- is tenant in token, header, path, host, gateway context, or combination?
- are mismatches rejected?
- where is authorization enforced?
- is tenant context available in JAX-RS filters/resources?

Data:
- database per tenant, schema per tenant, shared tenant_id, RLS, or another model?
- do repository/mapper methods require tenant?
- are global/admin queries explicit?
- are migrations tenant-aware?

Configuration:
- where is tenant-specific config stored?
- are catalog/pricing/rules tenant-specific?
- are tenant configs versioned/effective-dated?
- is fallback allowed or fail-closed?
- how is config drift detected?

Cache and integration:
- are cache keys tenant-aware?
- are external endpoints/credentials tenant-specific?
- are secrets referenced rather than stored in tenant config?

Events and jobs:
- do Kafka/event contracts include tenant?
- is partitioning tenant-aware?
- are jobs scoped per tenant?
- is reconciliation tenant-aware?

Observability and operations:
- do logs include tenant context safely?
- are tenant IDs allowed as metric labels?
- can support identify impacted tenants during incident?
- is tenant config change audited?

Do not infer these from product domain alone. Find evidence in code, database schema, token claims, gateway config, deployment manifests, event schemas, runbooks, and team onboarding sessions.


38. Senior Mental Model

Multi-tenancy is a chain.

identity -> tenant resolution -> authorization -> data access -> business rules -> cache -> events -> jobs -> observability -> audit

The chain is only as strong as its weakest link.

A senior engineer does not ask only:

Did we add tenant_id?

A senior engineer asks:

Can tenant context be proven correct at every boundary, including async, cache, jobs, events, logs, and configuration?

39. Practical Exercises

  1. Find one existing endpoint and trace how tenant is resolved.
  2. Find one repository method and verify whether tenant is mandatory.
  3. Inspect one cache key and check tenant/version dimensions.
  4. Inspect one event schema and check whether tenant is required.
  5. Inspect one scheduled job and check whether it is tenant-scoped.
  6. Find one tenant-specific config and check owner/version/effective date.
  7. Check whether tenant appears in logs, traces, and metrics safely.
  8. Look for fallback behavior when tenant config is missing.

40. Part Summary

You should now be able to reason about:

- tenant as a technical and business boundary
- trusted vs untrusted tenant signals
- tenant resolution lifecycle
- explicit vs implicit tenant context
- tenant-aware routing
- database isolation models
- tenant-aware repositories and SQL
- tenant-aware catalog/pricing/rules
- tenant-safe cache keys
- tenant-aware events, jobs, and integration credentials
- observability and audit risk
- PR review for tenant-sensitive changes

Next part: secret management and secure configuration — because once configuration becomes environment-aware and tenant-aware, secret handling, rotation, and redaction become production-critical.

Lesson Recap

You just completed lesson 40 in build core. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.