Migrate media libraries to Azure Blob Storage
Overview
NOTE: This article applies to existing Sitefinity Cloud PaaS customers who have purchased the Blob Storage add-on or have been migrated to the unified Sitefinity Cloud infrastructure (where the Developer Extensions toggle is enabled).
This guide describes the required steps to migrate your existing media libraries in Sitefinity Cloud from Database storage to Azure Blob Storage.
Prerequisites
The following is required before you start the migration:
- Blob Storage add-on is provisioned: The Sitefinity Cloud team has set up the Azure Storage account for your project and configured each environment to work with a dedicated blob container.
- Scheduled maintenance window for Production environments (recommended for large libraries): Because the migration is a long-running operation, libraries containing thousands of media items should be migrated during off-peak hours to minimize application load.
- You have the required access: Make sure you have access to the Sitefinity backend UI (for the Sitefinity backend UI approach) or to the project codebase (for the Sitefinity CMS API approach).
Migration workflow
Recommended migration sequence
We recommend the following migration sequence:
- Migrate media to the Staging/Authoring environment first.
Avoid migrating directly to Production unless Production is your only content editing environment. - Propagate the blob data to the Production environment using Site Sync.
Once the migration is complete on Staging/Authoring and the content is validated, use Site Sync to sync the blob items to Production. - Sync non-Production environments using the
DB.RestoreBetweenEnvironmentspipeline after migration to Production is stable.
This sequence minimizes any risk for your Production environment and takes advantage of the embedded blob sync in Site Sync functionality and the DB.RestoreBetweenEnvironments pipeline.
Supported migration path
IMPORTANT: Direct migration from File System storage to Azure Blob Storage is not supported. Attempting to migrate libraries from File System directly to Azure Blob Storage will result in items not being transferred correctly.
If your media items are currently stored in the file system, you must use the following migration path:
File System → Database → Azure Blob Storage
First, you move the storage provider from File System to Database (default option). Set the storage provider to Database and run MoveItemsToStorageProvider. Once all media items are confirmed in the database, proceed with the steps in this guide to migrate them from the Database storage to Azure Blob Storage.
Migrate libraries via the Sitefinity backend UI
This approach is suitable for migrating individual libraries through the Sitefinity backend interface — no code deployment is required. Perform the following:
- Log in to your Sitefinity backend.
- Navigate to Content » Images (or Documents & Files / Videos depending on the library type).
- On the Images page, expand the Actions menu of the library that you want to move to another storage and click Library properties. The Library properties page opens.
- In the Storage provider dropdown, change the provider from the Database (default) to Azure Blob Storage.
- Save your changes.
Sitefinity will start transferring the binary data for all items in that library to Azure Blob Storage. - Repeat the above steps for each media library.
NOTE: The migration runs in the background. For large libraries, it may take significant time to complete. You can monitor the progress in the backend when you open the library or in the Sitefinity application logs at
App_Data/Sitefinity/Logs/. The site remains operational during the migration - already transferred items will be served from Azure Blob Storage while not-yet-transferred items continue to be served from the database.
If the migration operation gets interrupted, you can safely resume it:
The already transferred items are not transferred again. If an individual item has failed to transfer (for example, due to a network error or a corrupt binary), the failure is logged as an error in Sitefinity application logs. Re-running the migration retries only previously failed items and skips items that were transferred successfully.
To verify the migration is complete, confirm that any item's URL in your Sitefinity backend resolves to https://<storage-account>.blob.core.windows.net/... and not to a database-served path. If no further migration activity appears in the logs, the transfer is successful.
You can also verify this via the Azure Portal by navigating to your Azure Storage account » Containers and selecting the environment container (for example, Staging). Make sure all media files are available.
Migrate libraries using Sitefinity CMS API
This approach uses the Sitefinity CMS LibrariesManager and BlobStorageManager to programmatically migrate one or all libraries. It is suitable when you need to migrate many libraries in bulk, when you want to automate the migration as part of a deployment, or when you want more control over the process.
All code samples below assume a valid Sitefinity application context (for example, running from a custom module, a page event handler, or a maintenance page in the CMS backend).
Migrate a single library
The following sample changes the storage provider for a single image album and starts moving its items:
using Telerik.Sitefinity.Libraries.Model;
using Telerik.Sitefinity.Modules.Libraries;
public void MigrateAlbumToBlobStorage(string albumName, string newBlobStorageProvider)
{
var librariesManager = LibrariesManager.GetManager();
// Get the album by name
var album = librariesManager.GetAlbums()
.FirstOrDefault(a => a.Title == albumName);
if (album == null)
throw new ArgumentException($"Album '{albumName}' not found.");
// Get all images in the album that are not already in the target provider
var imagesToMigrate = librariesManager.GetImages()
.Where(img => img.Parent.Id == album.Id
&& img.BlobStorageProvider != newBlobStorageProvider)
.ToList();
if (!imagesToMigrate.Any())
{
// Nothing to migrate — already on the target provider
return;
}
// Change the storage provider and move items
librariesManager.MoveItemsToStorageProvider(imagesToMigrate, newBlobStorageProvider);
librariesManager.SaveChanges();
}
NOTE:
MoveItemsToStorageProvideris a long-running operation. In case it does not complete (for example, due to a timeout, network error or application restart), it can be safely resumed. The media items already transferred to the new storage provider are detected by theBlobStorageProvidercheck and skipped.
To verify that the migration is complete, check the Sitefinity application logs (App_Data/Sitefinity/Logs/) and search for entries related to blob migration or MoveItemsToStorageProvider. If no further migration activity appears in the logs, the process completed successfully.
You can also verify programmatically by querying for items where BlobStorageProvider != newBlobStorageProvider - the zero count (0) confirms that all items are transferred.
Migrate all libraries in bulk
The following sample iterates over all image albums, document libraries, and video libraries and migrates them to the Azure Blob Storage in bulk:
using Telerik.Sitefinity.Libraries.Model;
using Telerik.Sitefinity.Modules.Libraries;
public void MigrateAllLibrariesToBlobStorage(string newBlobStorageProvider)
{
var librariesManager = LibrariesManager.GetManager();
// Migrate all image albums
foreach (var album in librariesManager.GetAlbums().ToList())
{
MigrateLibraryItems(
librariesManager,
librariesManager.GetImages()
.Where(img => img.Parent.Id == album.Id
&& img.BlobStorageProvider != newBlobStorageProvider)
.ToList(),
newBlobStorageProvider,
$"Album: {album.Title}");
}
// Migrate all document libraries
foreach (var docLib in librariesManager.GetDocumentLibraries().ToList())
{
MigrateLibraryItems(
librariesManager,
librariesManager.GetDocuments()
.Where(doc => doc.Parent.Id == docLib.Id
&& doc.BlobStorageProvider != newBlobStorageProvider)
.ToList(),
newBlobStorageProvider,
$"Document library: {docLib.Title}");
}
// Migrate all video libraries
foreach (var videoLib in librariesManager.GetVideoLibraries().ToList())
{
MigrateLibraryItems(
librariesManager,
librariesManager.GetVideos()
.Where(vid => vid.Parent.Id == videoLib.Id
&& vid.BlobStorageProvider != newBlobStorageProvider)
.ToList(),
newBlobStorageProvider,
$"Video library: {videoLib.Title}");
}
}
private void MigrateLibraryItems<T>(
LibrariesManager manager,
IList<T> items,
string newBlobStorageProvider,
string libraryDescription)
where T : MediaContent
{
if (!items.Any())
{
// All items already in the target storage provider
return;
}
manager.MoveItemsToStorageProvider(items, newBlobStorageProvider);
manager.SaveChanges();
}
RECOMMENDATION: For very large libraries, consider processing the items in batches (for example, 500 items at a time) to minimize memory pressure and allow partial progress to be saved between batches. Adjust the batch size based on the average file size in your libraries.
Verify the migration is complete
After migrating a media library, verify that the transfer completed successfully. To do this:
-
Spot-check items in your Sitefinity backend: Navigate to the migrated library (under Content » Images) and confirm that images are loading correctly.
-
Inspect the media item URL: Right-click an image item in the backend or on the frontend and copy the image URL. After the migration, the item's URL should resolve to Azure Blob Storage (for example,
https://<storage-account>.blob.core.windows.net/<container>/...) and not to a database-served path. -
Validate via the Azure Portal: Navigate to your Azure Storage account » Containers and select the environment container (for example,
Staging) to confirm the migrated media files are available. -
Review Sitefinity application logs: Check
App_Data/Sitefinity/Logs/for any errors during the transfer. Items that have failed to transfer appear as logged entries and you can retry them by re-running the migration operation.
Keep Sitefinity Cloud environments in sync after the migration
Once you have migrated your media libraries to one Sitefinity Cloud environment, you need to propagate the blob data to the other environments. Do not repeat the full migration process but use the built-in sync mechanisms instead.
From non-Production to Production: Use Site Sync
When you use Site Sync to promote content from Staging/Authoring to Production, blob items are automatically synchronized as part of the operation:
- Items available in the source (Staging/Authoring) container are copied to the target (Production) container.
- Items available in the target container but not in the source container are deleted from the target container.
No additional steps are required - the blob sync task is embedded in the Site Sync workflow. Site Sync evaluates all items in the source blob container across all libraries and folders. Every media file stored in Azure Blob Storage for the source environment is included - there is no folder-level or library-level filtering.
From Production to non-Production: Use DB.RestoreBetweenEnvironments pipeline
The DB.RestoreBetweenEnvironments pipeline restores the database from one Sitefinity Cloud environment to another. It includes a dedicated task that syncs the blob containers between environments alongside the database restore:
- Blob files in the source container are copied to the destination container.
RECOMMENDATION: This is the recommended approach for syncing from Production back to a non-Production environment.
When to use the DB.RestoreBetweenEnvironments pipeline:
- When you want to bring a non-Production environment fully in line with Production — both the database and media libraries. This is the standard way to refresh a non-Production environment with live data.
- When your media libraries were uploaded or migrated directly to Production, use this pipeline to propagate the blob data back to Staging/Authoring, so these environments reflect the latest state.
- When resetting a Sitefinity Cloud environment to a known-good state (for example, after a failed deployment or data corruption), running this pipeline ensures both the database and blob storage remain consistent with the source environment.
NOTE: This pipeline is not a substitute for Site Sync when promoting content from non-Production environments to Production. Use Site Sync for that purpose.
Best practices
| Practice | Details |
|---|---|
| Migrate to Staging/Authoring environment first | Your Production environment should receive blob data via Site Sync or the DB.RestoreBetweenEnvironments pipeline. This reduces the risk of service disruption in case the migration encounters an issue. |
| Migrate during off-peak hours for large libraries | Because the migration operation reads and writes large volumes of data, scheduling it during low-traffic periods minimizes the impact on the live site. |
| Process libraries individually for very large sets | If you have libraries with tens of thousands of items, consider migrating one library at a time to monitor progress and reduce the risk of performance degradation. |
| Safely resume an interrupted migration | If the migration operation is interrupted (due to a timeout, a corrupt binary, etc.), re-running it will only process items that have not yet been transferred. There is no risk of double-transferring the same items. |
| Spot-check the migrated media items | After migrating a library, spot-check several items in your Sitefinity backend and on the website to confirm they are served correctly. |
Troubleshooting
Migration times out or appears to stall
The migration operation runs in the background and can survive an HTTP request timeout. However, you may not receive a confirmation on the UI.
Cause: Large volume of items; App Service request timeout is enforced at the platform level and cannot be increased via web.config.
Action: Check the Sitefinity application logs (App_Data/Sitefinity/Logs/) to confirm the background transfer is progressing. Re-run the migration code (already transferred items will be skipped). For very large libraries, consult with the Sitefinity Cloud team.
Media items not loading after migration
After changing the storage provider, media items return 404 error or images are broken.
Cause: The blob storage provider name in the migration code does not match the provider configured in LibrariesConfig.config.
Action: Open App_Data/Sitefinity/Configuration/LibrariesConfig.config and locate the exact name of the Azure Blob Storage provider entry (for example, AzureBlobStorage). Ensure the same name is used in your migration code or in your Sitefinity backend.
Environments are out of sync after migration
Media items that are available in one environment are missing in another environment.
Cause: Blob containers are not automatically synced between your environments after the migration.
Action: Use Site Sync to promote the content from Staging/Authoring to Production. Use the DB.RestoreBetweenEnvironments pipeline to sync from Production back to a non-Production environment.