Profile API
| Role | The single read API for the unified customer profile. It serves every channel read from the D3 operational profile, and its projection workers keep D3 current from MDM's events |
| Technology | A custom service on AKS, in Node 22 or Java, which is not yet chosen. The API runs on the web node pool under HPA, scaled on CPU and requests per second. The workers run on the workers pool under KEDA, scaled on Service Bus queue depth (draft §05) |
| Decided by | The draft's register marks it Decided, but no decision in §10 names it. D-08 decides its store and D-09 its cache |
| Status in the draft | Decided. Its store and cache are still Validate V-10: Cosmos RU and Redis capacity at peak |
| Owner | None named |
| Register row | Components |
The source throughout is the target architecture draft (UC-ARCH-002 v3). Section numbers refer to it.
Its role
Channels learn who the customer is and what they hold from the Profile API. It answers from a projection, not from the system of record. MDM masters the profile, and the projection workers write each mastered outcome into D3. The Profile API then reads D3 back. On the dashboard read path, the BFF calls it alongside PingAuthorize's visibility decision and composes the page from the two. The draft's rule for login is "No MDM, ECR or BU call on login", and the Profile API is the component that allows it.
§11 also calls D3 the Customer Profile Store. The two names mean one store, and the Profile API is the only way into it. §12 is explicit: "no consumer gets direct database access."
Why a projection behind an API
Channel availability no longer depends on MDM's. The failure table says "MDM down: registration returns 202 Pending; reads are unaffected." MDM's own pipeline draws inquiry APIs serving the portal directly (see MDM). That would put a platform built around data lakes on a login path that targets 99.95% availability.
It removes the login-time fan-out. The MVP composes the dashboard by calling BU Data APIs at login. That path has to carry the ADS's 1,200 rps against FCC's documented 25 TPS (R2.4). A projection calls no BU at read time. R6.1 ruled the pattern out for MVP1 because it had no freshness contract. The draft now supplies that contract, and observation 0004 accepts the model, provided that D3 can carry everything the dashboard shows.
One API means the read contract lives in one place. seq, stale, merge redirects and ontology_v are handled behind the API. Without it, every consumer of D3 would implement them again.
What a read returns
- One customer, one jurisdiction. The read is keyed on the
rel_idin the session token. A customer with norel_idnever reaches the Profile API, because the BFF sends them to onboarding status (§04, Fig 05). - One document. Container
profile, partition/rel_id, id{jurisdiction}:{ontology_v}. The facets arevisible_products[],benefits.claims,consentandrelationship(§02). - From the local region only. Reads go cache-aside through Redis with a 60 s TTL, then to the local Cosmos DB replica at Session consistency. A read never crosses regions.
- With its freshness attached. Every response carries
seqandstale.stale=trueis set when projection lag passes its threshold, and the UI shows it (§09). - Through a merge.
customer.merged.v1turns the losing document into a tombstone that redirects to the survivor, and both cache keys are cleared (§02).
The consent facet is what visibility uses. Actions make a live OneTrust check instead, on the action path, and the Profile API takes no part in that check.
How the projection workers keep D3 current
The register pairs the workers with the API, and they share the row's Decided status.
- They consume MDM's mastered outcomes from the regional Service Bus namespace. Sessions are keyed on
rel_id, so each customer's events arrive in order. seqguards every write, and the last writer wins onseq(D-08). A gap inseqpauses that customer's session and triggers an off-path fetch of an MDM snapshot through MuleSoft.- Each region projects independently into the shared multi-write Cosmos DB account. The two regions converge on one document without depending on Service Bus geo-replication (D-10).
- Redis invalidation is per region. "Correctness never depends on cache geo-replication."
- D3 can be rebuilt from the D4 journal. A rebuild replays into
profile_v{n}, reconciles, and switches by config. The rebuild is drilled twice a year (§09).
Service levels and failure behaviour
Every target is proposed and needs business sign-off (V-09).
| Objective | Proposed target |
|---|---|
| Profile API latency | p95 < 150 ms, p99 < 400 ms |
| Read-path availability, login to dashboard | 99.95% monthly. This covers the whole path, not the API alone |
| Projection freshness | p99 < 30 s from MDM publish to D3 write |
| Merge and unmerge propagation | < 2 min to D3, the ECR and CIAM |
| Region loss | RPO ≈ 0 for D3 and Redis; RTO < 5 min by GTM drain |
The draft states no throughput for the Profile API. V-10 sizes Cosmos DB and Redis "at peak with doubled writes" without saying what the peak is. The only throughput figure in the material is the ADS's 1,200 rps, which was set for the MVP's auth path. The MDM meeting brief applied it to the Profile API, and that application is ours, not the draft's.
| When this fails | The Profile API |
|---|---|
| MDM | Keeps answering from D3 |
| A BU or MuleSoft | Keeps answering. It calls neither |
| The projection lags | Answers with stale=true |
| A region | Is drained by GTM. The other region already holds full data and capacity |
| PingAuthorize | Still answers, but the BFF denies by default and the dashboard shows an explicit unavailable state |
The draft does not state what a read does when Redis is unavailable or Cosmos DB throttles. It does list the Cosmos 429 rate and the Redis hit ratio as health signals, beside Profile API p95 and p99, projection lag per region, and cross-region seq divergence (§07). Telemetry carries a salted hash of rel_id and never the raw value.
Who calls it
- The BFF, for the customer dashboard. This is the only consumer the read path draws.
- The Intelligence Layer. §12 routes parts of a question to "Profile API and MuleSoft Experience APIs."
- Advisor and contact-centre channels, probably. §11 says digital, advisor and contact-centre channels "share the same identity, profile and access layers," and Fig 07 gives each channel its own MuleSoft Experience API. The draft does not show whether staff channels call the Profile API directly or through MuleSoft.
What it is not responsible for
- Mastering. MDM matches, merges and issues
rel_id. The draft says D3 is "never a second MDM." - Deciding visibility. PingAuthorize decides and the BFF enforces. The Profile API returns the document and the BFF filters what the customer sees.
- Writes. Customer edits go through the action path to the system of record "and then flow back" (§11, card 5).
- Reading business units. It has no BU dependency at read time.
- Preferences and journey context. §11 gives each of these its own store.
Open items
- 54: what "governed" means. The draft calls this a "governed read API" but specifies no authorization at the API itself. The mesh authorizes the calling service, not the customer. With one caller, the BFF scopes the
rel_id. With the Intelligence Layer and staff channels also calling, the draft gives no rule that stops a caller from reading a customer it should not see. D-15 refuses to let a caller scope the customer on calls to business units. The draft does not apply that rule to its own read API. - 47: what feeds
benefits.claimsandvisible_products[], and whether balances are in scope. If balances need a read-time BU call, the Profile API stops being the whole read path. - 21: D3 and Redis are classed Confidential, below the Highly Confidential sources they aggregate.
- 46: how staff channels get a customer's
rel_id, and so what they send to this API. - 53: the Intelligence Layer can read business units through MuleSoft, which bypasses the projection.
- 23: whether the operational profile is funded and staffed. The draft names no owner for the API and does not choose its runtime language.
- Freshness starts at MDM publish. BU-to-MDM latency sits outside every SLO above, and products reach MDM in batch until business units emit ownership events (R1.3).