Federated Composition (JIT)
Framework M utilizes Just-In-Time (JIT) Composition instead of the deprecated "Proxy Hydration" over the network.
The Anti-Pattern: Proxy Hydration
Under the "Proxy Hydration" pattern, if a finance.Invoice DocType has a link to crm.Customer, the backend makes a secondary HTTP call to the CRM microservice to resolve the customer object before returning the invoice. This creates significant latency, hidden N+1 queries, and severe backend bottlenecking.
The Solution: Raw IDs & Frontend Composition
To stop hiding the network, the backend composition adapter strictly returns the raw ID of the foreign key (e.g., {"customer_id": "123"}).
The responsibility for resolving cross-service linked entities lies exclusively with the frontend UI. The frontend makes explicit asynchronous requests to the appropriate service endpoints, maximizing browser connection concurrency, caching, and maintaining a clear network boundary.
Service Namespacing & API Prefixing
To facilitate frontend-led entity resolution across heterogeneous macroservices, the framework employs a dynamic namespacing strategy:
- Namespaced Resource Keys: Resources can be referenced using a
service/resourcepattern (e.g.,finance/PurchaseInvoice). - Dynamic API Resolution: The frontend
DataProvideruses these namespaced keys to dynamically reconstruct the correct service-scoped API path (e.g.,/api/finance/{version}/PurchaseInvoice). - Architectural Isolation: This ensures that each macroservice maintains its own independent API namespace (
/api/{service}/{version}) while the central Shell or other MFEs can still resolve and interact with resources across the entire federated ecosystem. - Zero-Cliff Portability: MFEs remain agnostic of whether the backend is a monolith or a cluster of macroservices, as the URL resolution logic adapts automatically based on the environment configuration (
FRAMEWORK_API_VERSION) and injected service context.
Discovery-Driven Routing
Instead of hardcoding service locations, the framework uses a Discovery Handshake at startup.
- The Discovery Manifest: The Shell fetches a central manifest from
/api/gateway/remotescontainingDiscoveryUnitobjects. - Dynamic Base URLs: Each service (e.g.,
finance) declares its ownapiUrlandmetaUrl. - Intelligent Dispatch: The
DataProviderlooks up these URLs in real-time. A request forfinance/Invoiceis automatically dispatched to the exact base URL declared by thefinanceservice, even if it resides on a completely different domain.
This "Late Binding" of API endpoints allows developers to move services between Monolith and Macroservice modes without changing a single line of frontend code.