From a83ad9c94b235d6e9d59ea985d464a580b00e1b4 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 11 May 2026 17:49:29 +0000 Subject: [PATCH 1/2] Revise Fluid Framework Compatibility Considerations --- FluidCompatibilityConsiderations.md | 73 ++++++++++++++++------------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/FluidCompatibilityConsiderations.md b/FluidCompatibilityConsiderations.md index 1d47af770f0c..a6f29a34dfb2 100644 --- a/FluidCompatibilityConsiderations.md +++ b/FluidCompatibilityConsiderations.md @@ -2,35 +2,34 @@ ## Overview -Fluid Framework is a distributed system where multiple clients collaborate on shared documents in real-time. To understand why we need different types of compatibility, we must first recognize the two fundamental parts of the Fluid software: +Fluid Framework is a distributed system where multiple clients collaborate on shared documents in real-time. To understand why we need different types of compatibility, we must first recognize three fundamental aspects of the Fluid software: -1. **Code**: APIs (public and internal) and Behavior (or logic) -2. **Data**: Ops and Summaries (or snapshots) +1. **Build Time**: What happens during development and build of projects using Fluid. Includes compatibility of package dependencies and TypeScript types. +2. **In Memory**: What happens at runtime in memory. Includes compatibility of runtime behaviors and data structures. +3. **Serialized Data**: Ops and Summaries (or snapshots). Includes anything which leaves the memory of the specific JavaScript context which created it. -The interaction between code and data, combined with Fluid's distributed architecture, creates four distinct dimensions of compatibility that must be carefully managed: +Combined with Fluid's distributed architecture, these aspects create four distinct dimensions of compatibility that must be carefully managed: ```mermaid flowchart TD - A[Code] --APIs--> B[Public APIs] - B --API stability--> C[API compatibility] - A --API/Behavior--> D[Layered architecture] - D --Interactions between layers--> E[Layer compatibility] - - F[Data] --Ops--> G[Multi-client collaboration] - G --Collaboration via ops--> J[Cross-client compatibility] - F --Ops/Snapshots--> I[Persistence] - I --Read saved files--> H[Data-at-rest compatibility] + BuildTime[Build Time] --APIs--> TypeScript + TypeScript --TypeCheck--> PackageCompat[Package Compatibility] + + InMemory[In Memory] --External APIs/Behaviors--> CustomerUse[Use by customer] + CustomerUse --Run Application--> PackageCompat + InMemory --Internal APIs/Behaviors--> LayeredArch[Layered architecture] + LayeredArch --Interactions between layers--> LayerCompat[Layer compatibility] + + SerializedData[Serialized Data] --Ops--> MultiClient[Multi-client collaboration] + MultiClient --Collaboration via ops--> CrossClientCompat[Cross-client compatibility] + SerializedData --Ops/Snapshots--> Persistence[Persistence] + Persistence --Read saved files--> DataAtRestCompat[Data-at-rest compatibility] ``` -### How Code and Data create Compatibility Dimensions +### How These Aspects Create Compatibility Dimensions -**From Code:** - -- **API compatibility** arises because applications depend on public APIs that are released across versions (including alpha and beta APIs). Applications need a stable, predictable upgrade path as Fluid releases new package versions. +- **Package compatibility** arises because applications depend on Fluid packages using version ranges which guarantee compatibility according to our [API support levels](./docs/docs/build/releases-and-apitags.mdx#api-support-levels) for both Type compatibility and runtime behavior. - **Layer compatibility** arises because Fluid's modular design consists of four distinct layers (Driver, Loader, Runtime, and Datastore), each of which can be versioned independently. These layers must interoperate at runtime even when they're at different versions. They interact by calling APIs (mostly internal) on other layers and the signatures and behavior of these APIs must be compatible. - -**From Data:** - - **Data-at-rest compatibility** arises because documents (stored as summaries/snapshots) may be dormant for extended periods and then reopened by clients running newer versions of Fluid. - **Cross-client compatibility** arises because multiple clients collaborating on the same document in real-time by exchanging ops may be running different versions of Fluid during rolling upgrades or version transitions. @@ -38,17 +37,20 @@ This document defines and explains each compatibility type in detail, describing > **Note:** This document does not specify the policies around what version compatibility matrix and guarantees we provide — it focuses on defining the compatibility types themselves. -## API compatibility +## Package compatibility -API compatibility implies that we cannot break existing APIs within the supported set of versions. For example, if we were to say we support compatibility of public APIs where the major version matches, we can only break them when releasing a major version (with reasonable documentation) but we cannot break them in minor or patch releases. +Package compatibility implies that we cannot break existing APIs within the supported set of versions. For example, if we were to say we support compatibility of public APIs where the major version matches, we can only break them when releasing a major version (with reasonable documentation) but we cannot break them in minor or patch releases. +See [API support levels](./docs/docs/build/releases-and-apitags.mdx#api-support-levels) for the actual guarantees we make. ### Motivation -Application developers need a clear, predictable upgrade path to newer Fluid versions. When API changes occur, documented and well-communicated breaking changes allow teams to plan and execute upgrades with confidence. +This allows users of our packages to use [dependency ranges](https://github.com/npm/node-semver) like "^2.100.0" providing predictable upgrade path to newer Fluid versions, ensuring big fixes are easy to integrate, and its clear when breaking changes need to be checked for. ## Layer compatibility -Layer compatibility implies that a single client can have different versions for different compatibility layers we support - Driver, Loader, Runtime and Datastore. For example, Driver is v1.0, Loader is v2.0, Runtime is v3.0 and Datastore is v3.1 on the same client. The APIs at the boundaries of these layers have strict compatibility requirements at _runtime_ (distinct from API compatibility, which is about in-code dependencies), to support the full range of versions that may be calling them from another layer. +Layer compatibility implies that a single client can have different versions for different compatibility layers we support - Driver, Loader, Runtime and Datastore. For example, Driver v1.0, Loader v2.0, Runtime v3.0 and both Datastore v3.1 and v3.2 are used on the same client. Multiple Datastore versions can coexist within a single Runtime because each datastore type may come from a separately-versioned package loaded through the runtime's code-loading registry. The APIs at the boundaries of these layers have strict compatibility requirements at _runtime_ (distinct from package and type compatibility, which are about build-time dependencies), to support the full range of versions that may be calling them from another layer. + +The APIs between these layers are often internal, and their implementations involve down casting, so special mechanisms beyond simple type checking are needed to ensure their compatibility. ### Motivation @@ -65,28 +67,35 @@ graph TD subgraph DataStore[DataStore - version D] DDSes[DDSes] end + subgraph DataStore2[DataStore - version E] + DDSes2[DDSes] + end end end FFS[Fluid Service] - Driver --> Loader - Driver --> FFS - Loader --> Runtime + Driver <--> Loader + Driver <--> FFS + Loader <--> Runtime style Driver fill:#4472c4,stroke:#2f5496,color:#fff style Loader fill:#548235,stroke:#3d5c28,color:#fff style Runtime fill:#c55a11,stroke:#a04a0e,color:#fff style DataStore fill:#5b9bd5,stroke:#4a8bc4,color:#fff + style DataStore2 fill:#5b9bd5,stroke:#4a8bc4,color:#fff style DDSes fill:#5b9bd5,stroke:#2f5496,color:#fff,stroke-width:1px + style DDSes2 fill:#5b9bd5,stroke:#2f5496,color:#fff,stroke-width:1px style FFS fill:#7030a0,stroke:#5a2680,color:#fff ``` +Arrows depict data flow between components. + This diagram shows different Fluid layers with different versions in a client: - **Driver layer**: Fluid package version A. - **Loader layer**: Fluid package version B. - **Runtime layer**: Fluid package version C. -- **Datastore layer**: Fluid package version D. +- **Datastore layer**: Fluid package version D and E. ## Cross-client compatibility @@ -131,11 +140,11 @@ graph LR FFS[Fluid Service] - Driver1 --> Loader1 - Loader1 --> Runtime1 + Driver1 <--> Loader1 + Loader1 <--> Runtime1 - Driver2 --> Loader2 - Loader2 --> Runtime2 + Driver2 <--> Loader2 + Loader2 <--> Runtime2 Client1 --A ops--> FFS Client2 --B ops--> FFS From a7ccea9be1318ed729f415ef0e714a7bdedc0c46 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Mon, 11 May 2026 20:06:54 +0000 Subject: [PATCH 2/2] Fix typos --- FluidCompatibilityConsiderations.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FluidCompatibilityConsiderations.md b/FluidCompatibilityConsiderations.md index a6f29a34dfb2..6e7bcb5733d8 100644 --- a/FluidCompatibilityConsiderations.md +++ b/FluidCompatibilityConsiderations.md @@ -44,13 +44,13 @@ See [API support levels](./docs/docs/build/releases-and-apitags.mdx#api-support- ### Motivation -This allows users of our packages to use [dependency ranges](https://github.com/npm/node-semver) like "^2.100.0" providing predictable upgrade path to newer Fluid versions, ensuring big fixes are easy to integrate, and its clear when breaking changes need to be checked for. +This allows users of our packages to use [dependency ranges](https://github.com/npm/node-semver) like "^2.100.0" providing predictable upgrade path to newer Fluid versions, ensuring bug fixes are easy to integrate, and it's clear when breaking changes need to be checked for. ## Layer compatibility Layer compatibility implies that a single client can have different versions for different compatibility layers we support - Driver, Loader, Runtime and Datastore. For example, Driver v1.0, Loader v2.0, Runtime v3.0 and both Datastore v3.1 and v3.2 are used on the same client. Multiple Datastore versions can coexist within a single Runtime because each datastore type may come from a separately-versioned package loaded through the runtime's code-loading registry. The APIs at the boundaries of these layers have strict compatibility requirements at _runtime_ (distinct from package and type compatibility, which are about build-time dependencies), to support the full range of versions that may be calling them from another layer. -The APIs between these layers are often internal, and their implementations involve down casting, so special mechanisms beyond simple type checking are needed to ensure their compatibility. +The APIs between these layers are often internal, and their implementations involve downcasting, so special mechanisms beyond simple type checking are needed to ensure their compatibility. ### Motivation