Skip to content

Proposal for #4699: opt-in VHDX compaction after WSL shutdown #40243

Open

Description

Related to #4699.

That issue already covers the disk reclaim problem itself, so this is not meant as a duplicate feature request. The goal here is to propose a more concrete implementation path that seems safer and easier to reason about in practice.

Summary

Introduce an optional VHDX compaction step triggered after WSL shutdown, instead of trying to compact dynamically while WSL is still running.

Motivation

Right now, freeing space inside WSL does not automatically free space on the Windows side. Even after large amounts of data are deleted inside the distro, the host-side .vhdx can remain heavily inflated until the user manually compacts it.

In practice, reclaiming that space usually ends up looking like this:

  • delete data inside WSL
  • run wsl --shutdown
  • compact the VHDX manually from Windows using optimize-vhd, diskpart, or another host-side workflow

That works, but it is not a great experience. It is easy to forget, depends on which Windows tools are available, and usually only gets done once the user is already running low on disk space.

I ran into this after generating a very large amount of logs inside WSL. After cleaning everything up, the distro looked fine from inside Linux, but the .vhdx on the Windows side was still huge and had to be compacted manually.

Proposal

Instead of introducing live or dynamic compaction while WSL is still active, a more conservative approach could be:

Support optional compaction after WSL is fully stopped.

High-level behavior

  • only evaluate compaction when:

    • wsl --shutdown is called, or
    • a distro has fully stopped
  • only run compaction if:

    • reclaimable space exceeds a threshold
    • a cooldown period has elapsed since the last compaction
  • feature is:

    • opt-in
    • disabled by default

Why this approach

Trying to compact while WSL is still running seems much more complex and much more likely to create edge cases.

Triggering compaction after shutdown has some clear advantages:

  • no active filesystem activity inside the distro
  • no running workload competing with the compaction step
  • lower risk around open handles or in-flight writes
  • it matches the manual workflow many users already rely on today

So this would not introduce a completely new maintenance pattern. It would mainly automate the one that users already perform manually.

Example configuration

Just as an illustration, this could potentially be exposed through .wslconfig or a similar mechanism:

[wsl2]
autoCompact=true
autoCompactThresholdGB=2
autoCompactCooldownHours=24

Non-goals

This proposal is intentionally conservative. It does not aim to:

  • compact while WSL is running
  • compact on every shutdown unconditionally
  • replace or conflict with other existing disk-management behavior

Implementation considerations

Some areas that seem relevant:

  • a trigger point after VM teardown in wslservice
  • estimating reclaimable space before deciding whether to compact
  • safe use of the existing host-side VHD compaction path
  • logging when compaction:
    • runs
    • is skipped due to threshold
    • is skipped due to cooldown
  • interaction with Docker Desktop and other WSL-integrated workloads

Open questions

  • what is the safest and most reliable way to estimate reclaimable space?
  • should this be global or per-distro?
  • should compaction run synchronously during shutdown or as a deferred background task after shutdown?

Closing thought

Overall, this feels like a practical middle ground: it avoids the complexity of live compaction while still solving a real usability issue by automating a shutdown-based reclaim workflow that already exists.

Activity

  1. github-actions commented on Apr 18, 2026

    @github-actions
    Contributor

    Logs are required for review from WSL team

    If this a feature request, please reply with '/feature'. If this is a question, reply with '/question'.
    Otherwise, please attach logs by following the instructions below, your issue will not be reviewed unless they are added. These logs will help us understand what is going on in your machine.

    How to collect WSL logs

    Download and execute collect-wsl-logs.ps1 in an administrative powershell prompt:

    Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/microsoft/WSL/master/diagnostics/collect-wsl-logs.ps1" -OutFile collect-wsl-logs.ps1
    Set-ExecutionPolicy Bypass -Scope Process -Force
    .\collect-wsl-logs.ps1
    

    The script will output the path of the log file once done.

    If this is a networking issue, please use .\collect-wsl-logs.ps1 -LogProfile networking instead, following the instructions in Collect WSL logs for networking issues

    Once completed please upload the output files to this GitHub issue.

    See Collect WSL logs (recommended method).

    If you choose to email these logs instead of attaching them to the bug, please send them to wsl-gh-logs@microsoft.com with the GitHub issue number in the subject, and include a link to your GitHub issue comment in the message body, and reply with '/emailed-logs'.

  2. Guayamose commented on Apr 18, 2026

    @Guayamose
    ContributorAuthor

    /feature

  3. github-actions commented on Apr 18, 2026

    @github-actions
    Contributor
    Diagnostic information
    Found '/feature', adding tag 'feature'
    
  4. Proman4713 commented on Apr 19, 2026

    @Proman4713

    i've been in #4699 for years, no one has responded, i can only wish someone acts on this issue

  5. lucasbasquerotto commented on Apr 19, 2026

    @lucasbasquerotto

    I'm expecting a solution for the automatic release of disk space in WSL2 for years, and #4699 does not seem to be addressed anytime soon. This issue about doing the compaction in shutdown seems more likely and easier to be implemented in the near future, so I hope it to be addressed soon.

  6. Guayamose commented on May 9, 2026

    @Guayamose
    ContributorAuthor

    I did some external validation outside the WSL repo to test whether the native Windows Virtual Disk API path is viable for this proposal.

    Prototype setup:

    • Windows 11 Pro 10.0.26200
    • WSL2 Ubuntu test distro
    • VHDX: ext4.vhdx
    • API path:
      • OpenVirtualDisk with VIRTUAL_DISK_ACCESS_METAOPS | VIRTUAL_DISK_ACCESS_GET_INFO
      • CompactVirtualDisk with COMPACT_VIRTUAL_DISK_FLAG_NONE
      • no AttachVirtualDisk
      • no DetachVirtualDisk
      • WSL was explicitly stopped before compaction

    Results:

    Test VHD size before data VHD size after creating 4 GiB non-zero file VHD size after deleting file VHD size after compaction Result
    No explicit fstrim 4,997,513,216 9,292,480,512 9,294,577,664 4,997,513,216 CompactVirtualDisk returned Win32 0
    With fstrim 4,997,513,216 9,292,480,512 9,294,577,664 4,997,513,216 CompactVirtualDisk returned Win32 0

    The generated file used non-zero data (openssl enc -aes-256-ctr) to ensure the VHDX backing file actually grew. In both cases, after deleting the file and shutting WSL down, CompactVirtualDisk recovered roughly 4 GiB and returned success.

    This does not prove the full product design yet, but it does suggest that the basic offline/shutdown-based API path is viable without needing live compaction or filesystem-aware attach/detach.

    Remaining questions:

    • behavior with Docker Desktop / other WSL-integrated workloads
    • behavior with larger or more fragmented VHDX files
    • sync vs deferred execution
    • threshold/cooldown policy
    • retry behavior if the VHD is temporarily still in use
  7. Guayamose commented on May 9, 2026

    @Guayamose
    ContributorAuthor

    Additional validation: in-use behavior.

    I tested the same disposable Ubuntu WSL2 distro while it was running. No real compaction was attempted while WSL was active.

    Test Running pre-check Command OpenVirtualDisk CompactVirtualDisk Result
    Normal dry-run guard Ubuntu running --dry-run skipped not called guard worked
    Forced metadata open Ubuntu running --dry-run --allow-running failed not called Win32 32 / ERROR_SHARING_VIOLATION

    The exact error for the forced metadata-open case was:

    Win32 32: The process cannot access the file because it is being used by another process.
    
  8. Guayamose commented on May 9, 2026

    @Guayamose
    ContributorAuthor

    I did a final round of external validation around Docker Desktop / WSL integration.

    The goal was to check whether the proposal can safely assume that wsl --shutdown leaves the target distro stopped, or whether external integrations can restart/keep it alive.

    Environment:

    • Windows 11 Pro 10.0.26200
    • Docker Desktop 4.71.0
    • Docker 29.4.1
    • WSL2 backend
    • Disposable Ubuntu WSL2 distro
    • Target VHDX: Ubuntu ext4.vhdx
    • The Docker VHDs were not compacted

    Results

    Test Docker integration for Ubuntu Docker state Time after shutdown WSL distros running Ubuntu state OpenVirtualDisk CompactVirtualDisk Result
    Enabled baseline dry-run enabled running 8s Ubuntu Running skipped not called target running
    Disabled dry-run disabled running before shutdown 8s none Stopped Win32 0 not called success
    Disabled compact disabled docker-desktop restarted N/A docker-desktop Stopped Win32 0 Win32 0 success
    Backoff check enabled running 0s Ubuntu Running N/A N/A target restarted immediately
    Backoff check enabled running 2s Ubuntu Running N/A N/A still running
    Backoff check enabled running 5s Ubuntu Running N/A N/A still running
    Backoff check enabled running 10s Ubuntu, docker-desktop Running N/A N/A Docker distro restarted too
    Backoff check enabled running 30s Ubuntu, docker-desktop Running N/A N/A both still running

    With Docker Desktop WSL integration enabled for Ubuntu, wsl --shutdown was not enough to keep the target distro stopped. Ubuntu was running again immediately after shutdown and remained running during the backoff checks.

    With Docker integration disabled for Ubuntu, the same offline Virtual Disk API path worked again:

    Test Size before Size after Delta OpenVirtualDisk CompactVirtualDisk
    Disabled integration compact 5,015,339,008 5,014,290,432 -1,048,576 Win32 0 Win32 0

    Interpretation

    These results suggest that a shutdown-triggered compaction feature should not be implemented as “blindly compact immediately after wsl --shutdown”.

    A safer shape would be:

    • opt-in only
    • evaluate after full shutdown
    • perform a final target-distro liveness check
    • attempt OpenVirtualDisk only if the target appears stopped
    • treat ERROR_SHARING_VIOLATION as a normal skip/defer condition
    • log why compaction was skipped
    • consider deferred retry/backoff instead of blocking shutdown synchronously

    Docker Desktop’s WSL integration appears to be a concrete example where an external integration can restart or keep a user distro alive after shutdown. That does not invalidate the proposal, but it means the implementation needs a final authoritative safety check close to the actual compaction attempt.

  9. Guayamose commented on May 10, 2026

    @Guayamose
    ContributorAuthor

    I opened an exploratory draft PR for the manual-command-first approach: #40481

    It intentionally implements only manual compaction:

    • wsl --manage <Distro> --compact
    • offline/stopped WSL 2 distros only
    • no automatic compaction
    • no shutdown hook
    • no .wslconfig
    • no threshold/cooldown
    • no Docker-specific behavior

    The goal is to validate the Virtual Disk API integration and CLI/service plumbing before discussing any automatic shutdown-triggered policy.

  10. kylemacfarlane commented on Aug 27, 2026

    @kylemacfarlane

    I never had good luck shrinking images myself, it would only ever take off 20-50%.

    I've given this new --compact command a try and it knocked a massive 80% off my main Ubuntu distro, 68GB > 12GB.

    But at the same time it wouldn't take a single byte off my Docker Desktop distro (docker_data.vhdx). It was stuck at 35GB and I still had to manually run a Optimize-VHD -Mode Full which took it down to 18GB.

  11. Guayamose commented on Aug 27, 2026

    @Guayamose
    ContributorAuthor

    I never had good luck shrinking images myself, it would only ever take off 20-50%.

    I've given this new --compact command a try and it knocked a massive 80% off my main Ubuntu distro, 68GB > 12GB.

    But at the same time it wouldn't take a single byte off my Docker Desktop distro (docker_data.vhdx). It was stuck at 35GB and I still had to manually run a Optimize-VHD -Mode Full which took it down to 18GB.

    Kyle MacFarlane (@kylemacfarlane)
    Thanks for the feedback, Docker uses a separate "docker_data.vhdx", while "--compact" only aims for the distro's main VHDX.

    Did "main\ext4.vhdx" get any smaller? (just to make sure u didn't have any problem with that)

    If so, I'm not really familiarize with Docker Desktop's WSL storage layout but if you feel other users are likely to face this too, I'll open a follow-up PR to implement it.

  12. kylemacfarlane commented on Aug 27, 2026

    @kylemacfarlane

    Docker Desktop's "main/ext4.vhdx" was only ever about 100MB. It's never suffered the growth issues of other images. Either it's mostly immutable and/or it gets nuked and remade regularly by updates. All the user data is in "disk/docker_data.vhdx"

    I think Docker Desktop used to have two distros "docker-desktop" and "docker-desktop-data" but they cleaned that up and now it's just one distro and "docker_data.vhdx" which must get mounted to the "docker-desktop" distro at some point.

    I would assume everyone using Docker on Windows will have this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions