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
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.
| Concern | Tenant-aware example |
|---|---|
| Security | user can only access tenant A |
| Data access | SQL filters by tenant |
| Catalog | tenant A sees product set X |
| Pricing | tenant A uses discount policy Y |
| Workflow | tenant A requires approval step |
| Integration | tenant A sends order to endpoint Z |
| Observability | logs and metrics include tenant context safely |
| Operations | incident 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.
| Source | Trust level | Notes |
|---|---|---|
| Verified token claim | high | if issuer/audience/key are validated |
| Gateway-injected header | medium/high | only if direct client cannot spoof it |
| Raw client header | low | easily spoofed |
| Path parameter | low/medium | must be authorized against identity |
| Subdomain | medium | depends on routing and cert model |
| Database ownership | high for existing record | must 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:
| Model | Description | Pros | Cons |
|---|---|---|---|
| Database per tenant | each tenant has separate DB | strong isolation | high operational cost |
| Schema per tenant | same DB, separate schema | moderate isolation | migration complexity |
| Shared tables with tenant_id | same tables, tenant column | efficient | highest query discipline risk |
| Row-level security | DB enforces tenant predicate | defense in depth | policy complexity |
| Deployment per tenant | separate app/runtime | strong operational isolation | expensive, 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:
| Key | Pros | Cons |
|---|---|---|
| tenantId | tenant-level ordering | hot tenant can bottleneck |
| quoteId | quote-level ordering | tenant events spread across partitions |
| tenantId+quoteId | scoped ordering | key design complexity |
| orderId | order lifecycle ordering | quote/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 mode | Symptom | Root cause | Detection |
|---|---|---|---|
| Cross-tenant data leak | user sees wrong quote/order | missing tenant predicate | audit/log/security test |
| Tenant context lost | async/event/job uses default tenant | context not propagated | trace/log with missing tenant |
| Cache pollution | wrong catalog/price returned | key omits tenant/version | cache key review |
| Wrong tenant routing | request hits wrong downstream | stale route/config | config version + route logs |
| Tenant config drift | pods behave differently | partial rollout/reload | config hash per pod |
| Unsafe tenant fallback | default catalog/pricing used | missing config hidden | fail-closed validation |
| High-cardinality metrics | observability degraded | tenant label everywhere | metrics cardinality review |
| Job scans all tenants | large incident/blast radius | missing job tenant scope | job dry-run/report |
| Event lacks tenant | consumer cannot isolate | schema/header omission | event 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
- Find one existing endpoint and trace how tenant is resolved.
- Find one repository method and verify whether tenant is mandatory.
- Inspect one cache key and check tenant/version dimensions.
- Inspect one event schema and check whether tenant is required.
- Inspect one scheduled job and check whether it is tenant-scoped.
- Find one tenant-specific config and check owner/version/effective date.
- Check whether tenant appears in logs, traces, and metrics safely.
- 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.
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.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.