diff --git a/acl/docs/README.md b/acl/docs/README.md
index 9353b15b7cf..81dd17d10af 100644
--- a/acl/docs/README.md
+++ b/acl/docs/README.md
@@ -12,7 +12,8 @@ Detailed documentation for Azure Container Linux.
## Operational Guides
-| Document | Description |
-| ------------------------------------------------------ | --------------------------------------------------------------------- |
-| [Build RPM Image](BUILD_RPM_IMAGE_README.md) | Building ACL images from RPMs |
-| [Container Image Preload](containerd-image-preload.md) | Baking OCI images into the containerd store with the Image Customizer |
+| Document | Description |
+| ------------------------------------------------------ | ---------------------------------------------------------------------- |
+| [Customizing ACL](customizing.md) | Customization options for ACL nodes and how A/B updates affect each |
+| [Build RPM Image](BUILD_RPM_IMAGE_README.md) | Building ACL images from RPMs |
+| [Container Image Preload](containerd-image-preload.md) | Baking OCI images into the containerd store with the Image Customizer |
diff --git a/acl/docs/customizing.md b/acl/docs/customizing.md
new file mode 100644
index 00000000000..cdb645a3f46
--- /dev/null
+++ b/acl/docs/customizing.md
@@ -0,0 +1,271 @@
+# Customizing Azure Container Linux: options and update behavior
+
+This document describes how ACL is built, what an OS update replaces, and which customization options
+are available today.
+
+---
+
+## 1. Image structure
+
+ACL ships as an immutable OS image with a fixed partition layout:
+
+| Area | Size | Mount | Role |
+| -------------------- | ------------------------- | ------------------ | ------------------------------------------------------------------- |
+| EFI System Partition | 256 MiB | `/boot` | Signed boot artifacts |
+| OS slot A | 1 GiB | `/usr` when active | One complete copy of the OS. Read-only and integrity-protected |
+| OS slot B | 1 GiB | `/usr` when active | The other copy. An update writes here, then activates it |
+| OEM | 128 MiB | `/oem` | Platform integration content |
+| ROOT | Grows to fill the OS disk | `/` | Writable. Contains `/opt`, `/var`, and the writable layer of `/etc` |
+
+Each OS slot also has a small companion partition holding the integrity hash tree for its `/usr`. Only
+the active slot is populated when the image is built.
+
+The following properties apply to every ACL node:
+
+- **`/usr` is read-only and integrity-protected.** Every block is verified at runtime against a hash
+ tree, whose root hash is recorded in a signed boot artifact. Any change to `/usr` changes that hash.
+- **There is no package manager and no RPM database.** OS packages cannot be installed, removed, or
+ patched in place on a running node.
+- **`/etc` is an overlay filesystem.** Its lower layer comes from the active `/usr` slot; its writable
+ upper layer is on ROOT.
+
+### Slot selection at boot
+
+The kernel is packaged as a signed Unified Kernel Image whose built-in command line is the same for both
+slots. Which slot to boot is supplied separately, by a small signed artifact stored alongside it on the
+EFI System Partition, and switching slots means replacing that artifact rather than rebuilding the image.
+
+This has two consequences for customization:
+
+- **Switching slots does not require re-signing.** One signed kernel image boots either slot.
+- **Changing the contents of `/usr` does require re-signing**, because it changes the integrity hash the
+ boot path verifies.
+
+## 2. Update behavior
+
+ACL updates are A/B updates, performed on the node by Trident, which is installed and enabled in the
+image. The update writes the complete new OS into the **inactive** slot, updates the boot artifacts on
+the EFI System Partition, and reboots into the new slot. The previous slot is retained, which is what
+makes rollback possible.
+
+An A/B update **replaces the entire OS**: kernel, system libraries, and every OS-supplied binary. It
+does so as a single atomic operation, and it is the mechanism by which an ACL node receives OS security
+updates, since OS packages cannot be patched in place.
+
+**An A/B update replaces exactly two things:**
+
+- the inactive OS slot, and
+- the signed boot artifacts on the EFI System Partition.
+
+**Everything else is shared between slots and is carried across the update unchanged:**
+
+- `/` (ROOT), including `/opt`
+- `/var`
+- the writable layer of `/etc`
+- `/oem`
+
+This is by design: it is how node state, logs, and configuration survive an OS update.
+
+### Scope of an update
+
+Customizations are generally orthogonal to A/B updates. An update generally runs
+and completes regardless of what has been added to the node.
+
+What varies is **coverage**. An A/B update covers the OS and only the OS. **Content placed outside `/usr`
+is not replaced by an update, and is not re-created or re-validated by one.** It remains exactly
+as it was, now running alongside a new OS version.
+
+This establishes a division of responsibility:
+
+| | Who updates it | On what schedule |
+| ---------------------------------- | --------------------------- | ------------------------------------------------------------ |
+| The OS (`/usr` and boot artifacts) | Delivered by the A/B update | Each OS release |
+| Anything added outside `/usr` | The operator | At the operator's discretion, and the operator must detect when the OS changes beneath it |
+
+Content that is independent of the OS version can often be left alone. Content that is tied to a specific
+OS or kernel version requires an operator-supplied mechanism to detect the change and install a matching
+build.
+Section 4 states, for each option, which of the two categories it falls into.
+
+## 3. Selecting an approach
+
+```mermaid
+flowchart TD
+ START([What is the node required to do?])
+
+ START --> Q1{1. Achievable with
Ignition and containers,
on the image as shipped?}
+ Q1 -->|Yes| O1["Option 1
Image as shipped.
Ignition for configuration,
Docker or Kubernetes for workloads."]
+
+ Q1 -->|No| Q2{2. Is it additive files under
/usr or /opt, with no change to
the kernel or bootloader?}
+ Q2 -->|Yes| Q2A{Is it versioned
independently of the OS,
or tied to an OS version?}
+ Q2A -->|Independently| O2A["Option 2: system extension,
tagged ID=_any.
Continues to match and merge
after an OS update."]
+ Q2A -->|Tied to the OS| O2B["Option 2: system extension,
tagged to an OS version.
Stops matching when the OS changes.
The operator detects that and
installs the matching build."]
+
+ Q2 -->|No| Q3{3. Can it live on the
writable filesystem?}
+ Q3 -->|"Yes, configuration"| O3A["Option 3
Configuration under /etc.
Persists unchanged. Nothing
re-applies it during an
in-place update."]
+ Q3 -->|"Yes, node-local state"| O3B["Option 3
State under /opt or /var.
Persists unchanged.
Kept current by the operator."]
+
+ Q3 -->|No| Q4["4. The change affects the kernel,
the bootloader, or the
contents of /usr."]
+ Q4 --> G1{Is the platform's Secure Boot
database under the operator's control,
or is production signing available?}
+ G1 -->|No| X1["Not available.
A modified /usr will not boot
under Secure Boot.
Revisit the requirement."]
+ G1 -->|Yes| G2{Can an image build, signing and
distribution pipeline be operated
for the life of the fleet?}
+ G2 -->|No| X2["Boots, but no update path.
The modified image becomes the only
source of OS updates for these
nodes, security updates included."]
+ G2 -->|Yes| O4["Option 4
Rebuild the image.
Changes are inside /usr, so updates
built from that image carry them."]
+
+ classDef managed fill:#d5efdc,stroke:#2d7a4b,stroke-width:1.5px,color:#14301f
+ classDef selfmanaged fill:#fdf1d6,stroke:#b8860b,stroke-width:1.5px,color:#4a3708
+ classDef unavailable fill:#eceff1,stroke:#607d8b,stroke-width:1.5px,color:#263238
+ class O1,O2A managed
+ class O2B,O3A,O3B,O4 selfmanaged
+ class X1,X2 unavailable
+```
+
+Green outcomes stay current across OS updates without further action. Amber outcomes require the operator
+to maintain the content against each OS release. Grey outcomes are not viable as stated.
+
+The two questions under option 4 are independent. Signing authority determines whether a modified image
+will boot at all; the ability to operate a pipeline determines whether those nodes keep receiving OS
+updates afterwards. Meeting the first without the second produces nodes that boot correctly and then
+stop receiving OS security updates.
+
+In text form:
+
+1. **Can the requirement be met by a container or first-boot configuration?** Option 1. The image stays
+ as shipped and nothing further is required.
+2. **Is it additive files under `/usr` or `/opt`, with no change to the kernel or bootloader?** Option 2.
+ Tag the extension `ID=_any` if it is versioned independently of the OS, or to a specific OS version if
+ it must be replaced whenever the OS changes.
+3. **Is it node-local state or configuration that is re-created whenever the node is reprovisioned?**
+ Option 3, noting that nothing re-applies it during an in-place update.
+4. **Does it require changing the kernel, the bootloader, or the contents of `/usr`?** Option 4 is the
+ only option that supports this, subject to the three requirements listed in section 4.
+
+Platform note: some platforms that provision ACL nodes on the operator's behalf expose a fixed
+configuration interface. Where that is the case, the available options are determined by that interface,
+independently of what the image supports. Consult the relevant platform's node configuration
+documentation.
+
+## 4. Options in detail
+
+Each entry states what it can change, what an A/B update does to it, and what it requires.
+
+### Option 1: Use the image as shipped
+
+Use the configuration and workload interfaces the image already provides.
+
+- **Runtime configuration:** Ignition, supplied as instance user data and applied on first boot.
+- **Workloads:** containers, run under Docker or Kubernetes.
+
+**Scope of change:** anything expressible as first-boot configuration or as a containerized workload.
+
+**Update behavior:** container workloads are unaffected by an OS update, because they are pulled by
+digest and reconciled by the orchestrator. Ignition runs on first boot only; it is applied again when a
+node is reprovisioned or reimaged, but not during an in-place A/B update. Files Ignition writes to
+`/etc` persist across an update unchanged.
+
+**Requirements:** none beyond the standard image.
+
+### Option 2: System extensions (sysext)
+
+A system extension is a self-contained image (an erofs, squashfs, or ext4 filesystem, or a directory)
+that `systemd-sysext` overlays onto the running system at boot. The sealed `/usr` is not modified, so no
+re-signing is required.
+
+**Scope of change:** files under **`/usr` and `/opt` only**. Content in an extension outside those
+two hierarchies, including anything under `/etc` or `/var`, is not merged and has no effect.
+
+**Where extensions are read from:** `/etc/extensions/`, `/run/extensions/`, and `/var/lib/extensions/`.
+When running in the initrd, `/.extra/sysext/` is also read, populated from the EFI System Partition.
+`/var/lib/extensions/` is the primary location for installed extensions; `/etc/extensions/` is
+appropriate for symlinks to images stored elsewhere.
+
+**Version matching.** Each extension carries an `extension-release.` file, whose name must match
+the image filename. Matching rules, enforced at merge time:
+
+| Field | Rule |
+| --------------- | ---------------------------------------------------------------------------------- |
+| `ID=` | Must match the host's `ID`, unless set to `_any` |
+| `SYSEXT_LEVEL=` | If `ID` is not `_any` and this field is defined, it must match the host |
+| `VERSION_ID=` | Used instead of `SYSEXT_LEVEL` when the latter is not defined; must match the host |
+| `ARCHITECTURE=` | Must match the running kernel's architecture, unless set to `_any` |
+
+An extension whose fields do not match the running OS is not merged.
+
+**Update behavior:** all extension search directories are on ROOT, which an A/B update does not replace.
+Extension files therefore remain on the node after an update, and are re-merged on the next boot
+**if they still match the new OS version** under the rules above.
+
+This produces two distinct outcomes, determined by how the extension is tagged:
+
+- An extension tagged `ID=_any`, versioned independently of the OS, continues to match and continues to
+ be merged.
+- An extension tagged to a specific OS `VERSION_ID` stops matching once the OS version changes, and is
+ no longer merged. The files remain on disk. Replacing it with a matching build is the extension
+ owner's responsibility.
+
+**Additional constraints:**
+
+- There is no dependency resolution. An extension must carry every file it needs that is not already in
+ the base image.
+- An extension must not ship `/usr/lib/os-release`, as this would override the host's OS version data.
+- Kernel modules are resolved from `/usr/lib/modules/$(uname -r)`. A module built for one kernel version
+ is not found by a different one.
+- While extensions are merged, `/usr` and `/opt` are read-only.
+- For shipping system services specifically, systemd documentation recommends Portable Services over
+ system extensions, as extensions provide no isolation from the host.
+
+**Note on configuration extensions (confext).** `systemd-confext` applies the same extension model to
+`/etc`. On the systemd version ACL currently ships (255), merging an extension makes the underlying
+hierarchy read-only for the duration of the merge. Because ACL requires a writable `/etc`, confext is not
+usable on ACL today.
+
+### Option 3: Write to the writable filesystem
+
+Write files directly to ROOT, typically under `/opt` or `/etc`, using a provisioning script or another
+first-boot mechanism.
+
+**Scope of change:** anything on the writable filesystem.
+
+**Update behavior:** content persists across an A/B update unchanged. It is not replaced, updated, or
+validated against the new OS version. If the mechanism that placed the content runs only at build time
+or first boot, it does not run again during an in-place update.
+
+### Option 4: Rebuild the image
+
+Produce a modified ACL image using Azure Linux Image Customizer, changing content inside `/usr`.
+
+**Scope of change:** anything in the image, including the kernel, the bootloader, and content under
+`/usr`.
+
+**Update behavior:** the changes are inside `/usr`, so they form part of what an A/B update replaces. An
+update built from the modified image carries them forward. An update built from an unmodified ACL image
+does not: the node boots a slot that does not contain them.
+
+**Requirements, all mandatory:**
+
+1. **Signing authority for the platform.** Changing `/usr` changes its dm-verity root hash. That hash is
+ carried in a signed boot artifact, so the artifact must be rebuilt and re-signed with a key that the
+ platform's Secure Boot database trusts. Where Secure Boot key enrollment is not under the operator's
+ control, this requires production signing. On hardware where the Secure Boot database is under the
+ operator's control, a self-generated key may be enrolled instead. This applies to changing the
+ *contents* of `/usr`; switching between slots does not require re-signing.
+2. **A base image containing an RPM database.** Image Customizer's UKI path queries the image's package
+ database. The standard ACL image does not ship one, so it cannot be used as a base directly.
+3. **Image distribution.** A modified image is the operator's artifact. Building, signing, storing,
+ replicating and delivering it to the fleet, including for subsequent OS updates, becomes the
+ operator's responsibility.
+
+## 5. Summary
+
+| | Modifies the image | What it can change | After an OS update | Who keeps it current |
+| -------------------------- | ------------------ | ------------------------------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------- |
+| **1. Image as shipped** | No | First-boot config; containerized workloads | Containers are reconciled by the orchestrator. Ignition-written files persist unchanged | The orchestrator, for workloads |
+| **2. System extension** | No | Files under `/usr` and `/opt` | Files persist; re-merged only if still version-matched | The operator, if the extension is tied to an OS version |
+| **3. Writable filesystem** | No | Anything on ROOT | Persists unchanged | The operator |
+| **4. Rebuilt image** | Yes | Anything, including the kernel | Replaced, by updates built from the modified image | The operator, as image publisher |
+
+## 6. Reference
+
+- `systemd-sysext(8)` for extension image formats, search paths, and version matching rules.
+- `systemd-stub(7)` for extension images carried on the EFI System Partition.
+- Azure Linux Image Customizer documentation for image rebuild configuration.