Skip to content
Home » VMware Horizon with FSLogix and storage optimization

VMware Horizon with FSLogix and storage optimization

A few months ago I’ve setup a new VMware Horizon desktop pool, based on Windows server 2019. Our previous desktop pool was based on Windows server 2018 R2 and used Persona as user profile solution. As Persona is deprecated and unusable on Windows 10 based operating systems) we had to look for another solution. Just at that time I found out about FSLogix, a solution that Microsoft acquired in late 2018, but which had already proven its value in application delivery and user profile management.

The idea was simple: Reduce the complexity of maintaining multiple desktop pools & master images containing their own set of software and provide the necessary security to give users only access to the software they need.


FSLogix is in fact a combination of products. You can seperate 3 major products

  • User profile & Office containers
  • Application masking (& redirection)
  • Java version control

In our setup, we used both the profile & container part and the application masking.


First we needed a solution to replace our Persona roaming profile solution. Neither roaming profiles, nor Persona (part of VMware Horizon) actually works nicely on Windows 10 and newer operating systems. VMware also has Dynamic Environment Manager either as part of Horizon or as standalone product, however we did not have it included in our Horizon standard suite (Side note: DEM standard has just been added to all Horizon suites as from version 7.13) So I came across FSLogix containers.
Remember those days when Microsoft introduced their “Universal Profile Disks”? Store user profiles from Remote Desktop Session hosts on a single network location so each user has its own user profile no matter what Remote Desktop Session Host they logged on to. It sure was an improvement cause it reduced the number of open connections to the profile server from tens or hundreds per user to a single connection for each user. A single connection to a VHD file, a virtual harddisk, containing the whole profile inside. Unfortunately they also came with some drawbacks, like fixed filenames being the GUID of the user, single session only, … Finally they also had their share of corruption and manual intervention to get things working again. Long story short: Been there, done that…
As a result, I was a bit sceptic about FSLogix containers, knowing they work in the same way: a virtual harddisk file containing the user profile, stored on a network share. But reviews on the Internet claimed the opposite. After using them in production for 6 months, I can confirm: FSLogix containers is definitely UPD 2.0 and more!

FSLogix containers consist of 2 types of containers. First we have the regular user profile container, which basically holds your c:\users\%username%\ folder inside. At logon, the VHD or VHDX (you can choose which format you want to use) of the user is mounted and a mount point is created to redirect c:\users\%username% to the contents of the VHD(X). Simple and efficient. Of course, that’s about what was universal profile disk too. So what’s so good about FSLogix then? A lot:

  • You can choose your own naming scheme for the files/folders in which you want to store the VHDs. No more unrecognizable GUIDs to search a profile for a user, you can even have each users’ VHD in it’s own subfolder.
  • Different access methods: direct, read-only, differencing disk. “Direct” is the same method as UPD: once a user has the profile open, it’s locked for all other users. “Read-Only” can be used as fall-back, when a user already has its VHD locked and wants to logon to another system with the same profile. Of courses, changes done in that session won’t be saved. “Differencing disk” doesn’t lock the VHD, but creates a differencing disk from the VHD to write all changes to. Once the users releases its profile, the differencing is merged into the parent VHD.
  • Exclusions: you can provide a list of folders to be excluded from the profile, so the profile doesn’t get bloated with unnecessary data. Although it’s very basic (only whole folders can be excluded, no wildcards allowed) it’s a good starting point to prevent your VHDs to grow too big.
  • There are also a lot of other configuration settings both available via GPO settings or registry settings.

The second type of FSLogix containers are Office containers (ODFC, Office Data File Container). Those are what made FSLogix so famous. What if you could remove all Office cached date (Outlook OST file, OneNote cache and backups, Skype cache, Teams cache) out of your profile. We all know how much space we could save in our userprofiles! Well, that’s what ODFC does. It takes all Microsoft Office cache data from the profile and stores it in a separate VHD(X) for that user. So why would you want to separate that data into another container with it’s own overhead? Well, this is actually all disposable data. Nothing that cannot be recovered or rebuild from scratch without loosing any data. So you could place those VHDs on a separate volume and exclude it from your daily backups. Most users won’t even notice if you’ve deleted their ODFC. Outlook will automatically recreate its OST. OneNote, Teams, … will automatically fill up their cache folders again. The only way you can see it, is that it all takes a bit longer when you start the office applications the first time.

In our environment we have implemented both user profile containers and office data file containers, of which some details are shown here:

# UsersTotal VHD size all usersAverage VHD Size/userMax. VHD SizeMin. VHD Size
User profile container200280 GB1,4 GB4,9 GB0,3 GB
Office data file container200415 GB2,1 GB12,4 GB0,3 GB

As you can see, the most storage is taken by the ODFC, which doesn’t surprise me. Although the Outlook cache period is limited to a few months, some users do have more than 5 (shared) mailboxes which starts to add up. Also Teams cache takes a big part once you start actively using Teams.

Optimize storage usage with deduplication

Of course, storage in a datacenter isn’t unlimited, I started looking at some options to efficiently use our storage to store the FSLogix containers. You all know that VHD(X) files “grow by design” and never shrink automatically, even if you delete all contents of the container. So that would pose a risk of always needed more storage to just save empty blocks… So I found some tools that can optimize the User profile and Office Data containers to cleanup unused space and shrink the VHD(X) files to the minimal size possible. I use the tool “ShrinkFSL“, created by David Ott. The nice thing about this tool is you can run it interactively with a nice GUI, but you can also run in a script, fully automated.
So what does it do? It mounts a VHD(X) container, runs a defrag on it so all free space is moved to the end of the disk and then does a shrink of the VHD(X) to make it actually smaller. Running this tool overnight on all the User Profile containers (the ones still in use are skipped of course but that’s just a few) saves us an average of 2GB each night. Same results for the Office Data containers. Not that big of a saving…

So what about enabling Windows deduplication on the volumes where the FSLogix containers are stored? Lots of users use the same applications, so the same data will be in all the users’ profiles. Same goes for the Office Data containers. It’s a rather small environment, so it should be possible to find the right balance between performance for the user and available resources for deduplication. Windows deduplication has the option to dedup “unlocked” blocks of large files that are in use.
So we enabled deduplication, choose “HyperV” as usage type, as we are going to dedup VHD(X) files, and made sure the “OptimizeInUserFiles” and “OptimizePartialFiles” are set to “true”. After some time to let it finish its initial deduplication run and settle down, we reached a savings rate of 70% for the User profile containers and 32% for the Office Data containers as you can see on the graph below (measured by checking the dedup savings each hour):

We are actually saving around 140GB of storage on each volume which isn’t bad at all.

Of course, we had to finetune things a little bit. By running the VHD(X) optimization script each night to optimize the sizes of the containers, lots of data blocks become free, but because we have Windows deduplication running, those blocks won’t become available for use until a garbage collection is run. So we updated our nightly optimization script to start a garbage collection job after the optimization script runs to free up all unused blocks and have to most storage available for the next working day. In the graph below, each vertical line represents the start of a new day. Shortly after midnight the optimization script runs, freeing up lots of disk space (graph shows percentage of free space on the volume with Office Data containers) and during the day, disk space is gradually filling up again. The smaller spike near the end of the day is probably caused by users logging of at the end of the day, letting windows deduplication doing it’s work more efficiently on unlocked files.


Let’s look at the user experience: The whole user profile is retained without noticeable impact on logon times (Imagine you would have done that with Persona…). Of course, unless you have tons of storage available, you’ll want to add some exclusions so that cache files, temporary files, etc. won’t be stored in the user profile unless they are absolutely needed.

Are there any drawbacks on this solution? Sure there are, it’s just a matter of how much impact they have to your environment. Running (background) deduplication requires resources of course, although in our environment we haven’t seen any impact on performance. Of course it all depends on the number of containers and their sizes and the storage back-end.

Running deduplication and a daily garbage clean-up wasn’t something our backup solution was happy about. Creating backups based on changed block tracking… well you can imagine there were a lot of changed blocks. On our user profile volume, the changed blocks were not that bad, but backup time did increase a bit. The volume with Office Data containers however was more problematic. The increase in changed blocks was so big, we decided to exclude that volume from our backups. After all, there’s nothing on that volume that can’t be automatically recreated by the Office applications (Outlook OST, search index, Teams cache, etc.).

In the end it all depends on your environment whether you enable deduplication or not, or maybe shrink the containers only once a week. I just wanted to show you that in a rather small environment, you can have a good user experience using FSLogix without needing huge amounts of storage.

Leave a Reply

Your email address will not be published. Required fields are marked *