---
title: Deploy to Windows servers
slug: cms-12/docs/deploying-to-windows-servers
docTags: 
createdAt: 2026-08-10T15:56:03.000Z
---

Deploy an Optimizely Content Management System (CMS) application to Windows servers using `dotnet publish`. The published output contains all required files and can be copied directly to one or more target servers — no separate Optimizely installation is needed.

To host the application on IIS, see [Microsoft Host ASP.NET Core on Windows with IIS](https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/?view=aspnetcore-5.0).

## Deploy a site

The following procedure shows how to deploy an Optimizely site from development to production. You can automate this using the `dotnet` command or other tools.

You need three artifacts to bring over to the production server:

- **Site** – the published application output (from `dotnet publish`).
- **SQL Server database** – stored content and so on.
- **Application Data** – media BLOBs, search index. These are files normally stored in `App_Data`.

:::hint{type="info"}
**Note**
The following steps assume you have an existing site and familiarity with IIS and SQL Server Management Studio.
:::

### 1. Create the deployment artifacts

Run `dotnet publish` from your project directory to produce a deployment-ready output folder:

```bash
dotnet publish -c Release -o ./publish
```

This restores NuGet dependencies, builds the project, and outputs all required files to the `./publish` folder.

If your project uses files in the `App_Data` folder (such as media BLOBs or search indexes), copy them into the publish output manually or include them in your project file so they are published automatically.

### 2. Deploy the artifacts on the target server

:::hint{type="info"}
**Note**
The following steps are performed on the target server and assumes you have moved the artifacts created in the previous section to the new server. The web server should have IIS and the [.NET 8 Hosting Bundle](https://dotnet.microsoft.com/download/dotnet/8.0) installed. You also need SQL Server Management Studio to connect to the database server.
:::

1. Attach the database. See [Attach a database on MSDN](http://technet.microsoft.com/en-us/library/ms190209.aspx).
   To complete this step, move the database files from the `App_Data` folder to the designated data folder for Microsoft SQL Server.
   You can also use backup or restore to attach a database. See [Backup and restore of SQL server databases on MSDN](http://technet.microsoft.com/en-us/library/ms187048.aspx).
2. Create a **new SQL Login**:
   1. Right-click on the **Security** node and select **New** > **SQL Login**.
   2. Select **SQL Server Authentication**.
   3. Unselect **User must change password at next login**.
   4. Under User Mapping, select the database and make sure the user is a member of the **db\_owner** group.
3. On the web server, create a **new folder** for your site (for example `c:\inetpub\Site1`), and copy the contents of the deployed site.
4. Open **Internet Information Services Manager** and connect to the web server.
5. Create a **new IIS site:**
   1. Right-click the **Sites** node.
   2. Select **Add Website**.
   3. Set the **Physical path** to the published app's root folder (the folder containing the generated `web.config`).
6. Update the `EPiServerDB` connection string in `appsettings.json` with connection details to the database (server, database, SQL login, and password).

:::hint{type="info"}
**Note**
For security and performance reasons always move media BLOBs to a folder outside the application root (as described in the next section), either on a fileshare or a local folder. Storing BLOBs in the *App\_Data* folder is only designed for development purposes.
:::

### 3. Add load-balancing support

This section describes how to enable load-balancing, configure [remote events](docId\:lD3CRU-O7TI5NsBNxmXFX), and external storage of [BLOBs](docId\:pRFJn3CvDaH82_HGivBtO) (files on a fileshare). The example uses the Azure service bus and the default provider for storage of BLOBs.

:::hint{type="info"}
**Note**
Use the dedicated [Azure Service Bus provider](docId\:yfZ87y0tFrQM_pS6j_tLS).
:::

1. Move the `Blob` subfolder of the `App_Data` folder to a shared server, such as the database server, and then share the folder. Give access rights for the share and the folder to the user running the Application Pool for the site in Windows.
2. Edit `appsettings.json` and add configuration for the file BLOB providers. Make sure the `Path` property points to the correct path of the shared folder in step 1:

```csharp
{
  "EPiServer":{
    "Cms":{
      "FileBlobProvider":{
        "Path": "\\dbserver\blobs"
      }
    }
  }
}
```

3. Clear the browser cache and test the setup by browsing the site. Images on the site should work as before but now are delivered from the shared location.
4. Configure the default provider for **remote events** by configuring the endpoints.
   The site is ready to be load-balanced.
5. Copy the site folder to a second server and create a site in IIS with the same settings as the previous server. No configuration changes are required.
6. Test remote events by logging in to one of the servers and publishing changes to a page. The published changes appear on the other server. Use the search functionality from both servers to verify it was configured correctly.

A hosting provider can help you load-balance incoming traffic between the servers. You also can use other software load-balancers such as [HAProxy](http://haproxy.1wt.eu/), [Network Load Balancing (NLB)](http://technet.microsoft.com/en-us/library/hh831698.aspx), or [Application Request Routing (ARR)](http://www.iis.net/downloads/microsoft/application-request-routing).

:::hint{type="info"}
**Note**
The core parts of CMS do not use Session State, but some functionality does, such as certain audience criteria. If your load-balanced setup requires session state, use sticky sessions (session affinity) on your load balancer, or configure a distributed session provider.
:::

If you are hosting on Optimizely Digital Experience Platform (DXP) or Azure App Service, enable **ARR Affinity** to ensure proper cache invalidation by remote events. In the Azure Portal, go to your App Service, select **Configuration > General Settings**, and set **ARR Affinity** to **On**.
