ADR-029: Schema Visualizer Scope, Discovery and Caching Without Platform Cache
Status
Accepted (2026-10-22).
Context
The SAS promises a data model diagram that never drifts from the deployed org (section 5.1). The Business Architecture page (Pillar A) draws it live. The earlier design in the Technical Guide had two problems:
- It cached the describe result in Platform Cache. The org has no Platform Cache partition, and the project decided against it.
- It drew edges from child relationships.
Accountalone carries hundreds of standard child relationships, so walking them costs CPU and fills the diagram with noise.
The page also needs two schemas: the inert Employer Hub model of the demo (shown by default) and the portfolio’s own model. The site guest, who has no read access on the Employer Hub objects, must see the same diagram as an administrator.
Decision
SchemaService.getSchemaGraph(scope) (public with sharing, @AuraEnabled(cacheable=true), API 64.0) builds the diagram for one scope, portfolio or employerHub. Any other scope throws an AuraHandledException.
- Discovery from the global describe keys only. One
Schema.getGlobalDescribe()per call, keys only. An object is a custom object of this org when its name ends in__cand has no namespace prefix (exactly one__). Names ending in__mdt,__e,__b,__x,__Share,__History,__Feedor__ChangeEventare dropped, and so are custom settings (DescribeSObjectResult.isCustomSetting()). - Scopes. An object whose name starts with
EH_belongs toemployerHub. Every other custom object belongs toportfolio. Each scope adds a standard allowlist:AccountandContactfor the portfolio, andAccount,Contact,Case,OpportunityandContractfor the Employer Hub. - Overrides in Custom Metadata.
Schema_Visualizer_Object__mdtrows (Object_API_Name__c,Scope__c,Hidden__c) move an object to a scope or hide it. Four shipped rows hide the internal objectsAPI_Rate_Window__c,API_Access_Request__c,Github_Cache__candJira_Cache__c(my decision, 2026-10-22). - Describe the filtered list only.
Schema.describeSObjects(names, SObjectDescribeOptions.DEFERRED)runs on the objects in scope, never on the whole org. - Edges from reference fields. An edge is a reference field whose target is in the same scope. It points from the object holding the field to its target. A field with a relationship order (
getRelationshipOrder() != null) is master-detail, and every other reference is a lookup. Child relationships are not read. - The only cache is the browser’s.
cacheable=truelets Lightning Data Service cache the answer on the client. There is no Platform Cache and no server cache. - The cost is shown. The response carries the server CPU time of the call (
cpuMs), and the page’s caption shows it with the object count, for example “9 objects, described in 96 ms of server CPU”.
Rationale
- It cannot drift. A new custom object appears on its own in the portfolio scope, and hiding or moving one is a metadata deploy, not a code change.
- The guest sees the same schema. Run as the real site guest (
SchemaServiceTest.guestDescribeMatchesAdmin), the global describe anddescribeSObjectsreturn the same objects as for an administrator, the fourEH_objects included, though the guest cannot read them. Describe does not filter by object permission, so the guest needs no object grant and no deploy-time snapshot (established 2026-10-22). Exposing names is acceptable because the repository is public. - It is cheap. Uncached in a scratch org, the portfolio scope (14 objects, 21 edges, 10 master-detail) took 141 ms of CPU and the Employer Hub scope (9 objects, 23 edges, 1 master-detail) took 96 ms, against a budget of 1,000 ms per call and the SAS limit of 5,000 ms per request.
SchemaServiceTest.eachScopeStaysUnderTheCpuBudgetasserts the budget.
Alternatives considered
| Option | Rejected because |
|---|---|
| Platform Cache for the describe result | The org has no partition, and the project decided against Platform Cache. |
Edges from getChildRelationships() |
Hundreds of standard child relationships on Account cost CPU and draw noise. |
| A schema snapshot taken at deploy time | It goes stale, which is what the diagram must not do. The guest describe result made it unnecessary. |
| A hard-coded list of objects | It drifts the first time an object is added. |
Implications
SchemaServicereads no records and exposes metadata only. The site guest holds class access to it throughPortfolio_Guestand nothing else for the diagram.- The
EH_Demo_Readpermission set (read on the fourEH_objects) is optional for administrators and is not assigned to the guest. c/schemaVisualizerdraws the result with the shared d3-force engine on desktop and tablet, and shows the object list on phones (ADR-020 amendment). Technical Guide section 2.4 describes it.- The class stays on API 64.0. From 67.0 Apex runs in user context by default, which would change the describe.