Reference Data Management
2026
Single governed source-of-truth for translations and cross-system code mappings. Transactional outbox + RabbitMQ Streams for cache-invalidation only; MongoDB + Redis read-through; BFF page-level aggregation; mobile offline bundle.
The problem
Across the Balady estate, dozens of services maintain their own copies of
translations, code mappings (e.g. service-category-id → display-name),
and lookup tables. Every team handles invalidation differently. Mobile
apps need offline access to a frozen subset.
The architecture
A central source-of-truth that serves reference data to .NET MVC, SPA + .NET BFF, mobile clients, Java services, and partner integrations.
The key constraint: RDM never writes to consumer databases. Consumers own their own caches and decide what to retain. RDM only fires cache-invalidation events when its data changes.
A set of Architectural Decision Records governs the design, including:
- Transactional outbox + RabbitMQ Streams for cache-invalidation only — direct publish can lose events on a crash and distributed two-phase commits are fragile across two datastores, so the outbox commits the event in the same transaction as the data write and a relay drains it, giving at-least-once delivery with no distributed-transaction coordinator
- MongoDB as the master store (schema-flexible reference data)
- Redis as the read-through cache
- A single stream partitioned by namespace — each consumer gets ordered processing within its own namespace and broker-level filtering instead of filtering every event itself
- BFF page-level aggregation — the SPA fetches a page’s reference data in one call
- Mobile critical-flow bundle — a frozen subset of high-priority data shipped with the app for must-work-offline screens
Onboarding a consumer is a configuration step rather than a project: parity-tested client libraries for the .NET and Java consumers bundle the resolver, cache, subscriber, and idempotency handling so every consumer behaves consistently. Resilience is by design — because consumers hold their own caches with TTL fallback and mobile ships a frozen critical-flow pack, products keep serving correct values even when the central service is degraded.
Pattern view — a single source of truth that emits cache-invalidation events; consumers own their own caches.
Outcome
One canonical authority for translations and codes. Consuming services no longer fork drift. Rolled out behind a single pilot service before broader onboarding.