Services Hosting & Servers Tools Blog Search Company TürkçeTR
Get a Quote

Windows hosting is a shared or VPS-tier hosting service delivered on Microsoft Windows Server with the IIS (Internet Information Services) web server, ASP.NET / ASP.NET Core, Microsoft SQL Server, and frequently the Plesk control panel. Compared with the PHP/MySQL ecosystem of Linux hosting, it is the unavoidable choice for applications tied to the.NET ecosystem, classic ASP sites, enterprise apps that depend on Windows-specific libraries such as Crystal Reports, and especially ERP/CRM-like systems with MSSQL dependencies.

This guide covers all of the practical details: IIS configuration, the correct installation of the ASP.NET Core Hosting Bundle, in-process / out-of-process hosting models, MSSQL connection string patterns, TLS management from the Plesk panel, application pool tuning, deployment strategies (Web Deploy, FTPS, GitHub Actions), and Windows hosting price ranges in Turkey. Every example is backed by commands, web.config / appsettings.json fragments, and PowerShell snippets taken from real production; no imaginary product recommendations or fake prices.

Related guides: What Is Hosting? Types and Pricing · Nginx vs Apache · Plesk Panel Management · MySQL vs PostgreSQL · Free SSL with Let's Encrypt · VPS Hosting Guide

What Is Windows Hosting and How Does It Differ from Linux Hosting?

The word "hosting" is technically neutral on its own — it provides access to a file system, a web server process, and an optional database. But the operating system choice determines which technologies your application can run. Linux shared hosting packages run a PHP interpreter on Apache or LiteSpeed and ship with MySQL/MariaDB. Windows hosting packages, on the other hand, run.NET runtimes that execute .aspx, .ashx, and .cshtml files on IIS, plus an optional MSSQL instance.

The critical practical difference: PHP sites run on both platforms — many Windows hosting providers offer PHP versions from 5.6 through 8.3. However, ASP.NET, ASP Classic, MSSQL, Crystal Reports, COM components, and IIS modules only run properly on Windows. If your codebase contains a web.config file, a System.Web.Mvc reference, or uses SqlConnection, Windows hosting is not a preference — it's a requirement.

Which Kinds of Applications Require Windows Hosting

  • Classic ASP sites: Legacy intranet and SMB systems still in production. No other platform interprets the .asp extension.
  • ASP.NET Web Forms (4.x): Traditional postback-based applications written in VB.NET or C#.
  • ASP.NET MVC 5: Built on top of System.Web, so it requires full Windows / IIS; not to be confused with ASP.NET Core MVC.
  • ASP.NET Core 6/8/9/10 (on the Windows side): Also runs on Linux, but Windows can be preferable for the IIS app pool, Windows Auth, and in-process hosting advantages.
  • Applications with heavy MSSQL dependencies: Systems that lean on stored procedures, Service Broker, FILESTREAM, and similar features.
  • Crystal Reports / SAP reporting integrated legacy applications.
  • Microsoft ecosystem products such as SharePoint, Exchange, and BizTalk.

Scenarios Where Linux Hosting Is the Better Choice

For PHP-based applications (WordPress, Laravel, Symfony, Magento, OpenCart), Node.js, Python (Django/Flask), Go, Ruby on Rails, and static site generators (Hugo, Jekyll, Astro), Linux hosting is both cheaper and a more natural ecosystem fit. For a deeper comparison see our Nginx vs Apache and LSCache Guide articles.

IIS: A Quick Look at Internet Information Services

IIS is the web server Microsoft ships free with Windows Server. As of 2026, the common versions are: IIS 10.0 shipped with Windows Server 2019, IIS 10.0 with Windows Server 2022 (with enhanced HTTP/3 support), and the new release in Windows Server 2025. Every modern Windows hosting provider runs at least IIS 10. Instead of a single nginx.conf-style config like Apache or Nginx, IIS works with per-site web.config XML files and a server-wide applicationHost.config.

IIS's core concepts: Site (a hostname / port binding), Application Pool (the process pool that manages worker processes), Virtual Directory and Application (sub-URL paths), Binding (HTTP/HTTPS port + hostname). Application pool isolation is similar to running each PHP-FPM pool under a separate user on Linux; if every site runs in its own pool, one crash won't affect the others.

web.config Structure

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
 <!-- Module for the ASP.NET Core application -->
 <handlers>
 <add name="aspNetCore" path="*" verb="*"
 modules="AspNetCoreModuleV2"
 resourceType="Unspecified" />
 </handlers>

 <aspNetCore processPath="dotnet"
 arguments=".\MyApp.dll"
 stdoutLogEnabled="false"
 stdoutLogFile=".\logs\stdout"
 hostingModel="InProcess" />

 <!-- HTTP -> HTTPS redirect -->
 <rewrite>
 <rules>
 <rule name="HTTPS Redirect" stopProcessing="true">
 <match url="(.*)" />
 <conditions>
 <add input="{HTTPS}" pattern="^OFF$" />
 </conditions>
 <action type="Redirect"
 url="https://{HTTP_HOST}/{R:1}"
 redirectType="Permanent" />
 </rule>
 </rules>
 </rewrite>

 <!-- Cache headers for static content -->
 <staticContent>
 <clientCache cacheControlMode="UseMaxAge"
 cacheControlMaxAge="30.00:00:00" />
 <mimeMap fileExtension=".webp" mimeType="image/webp" />
 <mimeMap fileExtension=".avif" mimeType="image/avif" />
 </staticContent>

 <!-- Brotli + Gzip -->
 <httpCompression>
 <dynamicCompression>
 <add mimeType="text/*" enabled="true" />
 <add mimeType="application/json" enabled="true" />
 <add mimeType="application/javascript" enabled="true" />
 </dynamicCompression>
 </httpCompression>
 </system.webServer>
</configuration>

web.config drops into the site directory similar to Apache's .htaccess; but because it is XML, the syntax is strict — a single missing closing tag knocks the whole site into 500 errors. Always validate it through our JSON / XML Formatter Tool or VS Code's built-in linter.

ASP.NET Core Hosting Bundle: Running.NET on IIS

ASP.NET Core (now simply called .NET, the cross-platform.NET starting with version 5) is not an IIS module; it uses a separate Kestrel server process running behind IIS as a reverse proxy. The single component that makes this architecture possible is the ASP.NET Core Hosting Bundle. Unless you install it on the server, your .NET 8 or .NET 9 applications will not start under IIS.

Microsoft's official documentation (learn.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/hosting-bundle) states that the Hosting Bundle includes three components: the.NET Runtime, the ASP.NET Core Module (ANCM), and the ASP.NET Shared Framework. Install order is critical — IIS first, then the Hosting Bundle; if you reverse the order, the module won't appear registered after iisreset and you'll need a repair install.

Installing the Hosting Bundle (PowerShell)

# First make sure the IIS role and required features are installed
Install-WindowsFeature -Name Web-Server `
 -IncludeManagementTools `
 -IncludeAllSubFeature

# Download.NET 9 Hosting Bundle (latest permanent link)
$bundleUrl = 'https://dotnet.microsoft.com/permalink/dotnetcore-current-windows-runtime-bundle-installer'
$bundlePath = "$env:TEMP\dotnet-hosting-bundle.exe"
Invoke-WebRequest -Uri $bundleUrl -OutFile $bundlePath

# Silent install
Start-Process -FilePath $bundlePath `
 -ArgumentList '/install /quiet /norestart' `
 -Wait

# Verify installed.NET runtime versions
dotnet --list-runtimes

# Restart IIS (mandatory after the Hosting Bundle install)
net stop was /y
net start w3svc

# Check ASP.NET Core Module version
Get-Item 'C:\Program Files\IIS\Asp.Net Core Module\V2\aspnetcorev2.dll' |
 Select-Object -ExpandProperty VersionInfo |
 Format-List FileVersion, ProductVersion

Among the silent install parameters, OPT_NO_X86=1 skips the 32-bit runtime (if you're only hosting 64-bit apps), and OPT_NO_RUNTIME=1 skips the runtime install for self-contained deployments. OPT_NO_ANCM=1 skips the ASP.NET Core Module — on a shared Windows host, you generally won't need this option because the module will already have been installed by the provider.

In-Process vs Out-of-Process Hosting

ASP.NET Core applications can run behind IIS under two different models. In the In-Process model, the Kestrel server runs inside the IIS w3wp.exe process — less network overhead, lower latency, but if the app pool crashes, Kestrel goes down with it. In the Out-of-Process model, Kestrel runs in a separate dotnet.exe process and IIS acts as a reverse proxy. Since.NET Core 3.0, in-process is the default.

  • In-process advantage: Roughly 5-10 microseconds lower latency per request; 20-30% more requests per second in AWS / Azure benchmarks.
  • Out-of-process advantage: Process isolation — an application failure does not bring down IIS. Safer for providers that host multiple sites in the same app pool.
  • Cases where in-process can't be used: If you want to host more than one ASP.NET Core application inside the same app pool, each must run separately in out-of-process mode.
  • Selection rule: With a single dedicated app pool, prefer in-process; in a shared / multi-tenant pool, prefer out-of-process.
<!-- Choosing hostingModel inside web.config -->
<aspNetCore processPath="dotnet"
 arguments=".\MyApp.dll"
 hostingModel="InProcess"
 stdoutLogEnabled="true"
 stdoutLogFile=".\logs\stdout">
 <environmentVariables>
 <environmentVariable name="ASPNETCORE_ENVIRONMENT"
 value="Production" />
 <environmentVariable name="COMPlus_EnableDiagnostics"
 value="0" />
 </environmentVariables>
</aspNetCore>

Application Pool Management and Tuning

Application pool is one of the most critical settings in IIS. All sites assigned to a pool run in the same w3wp.exe process; they share the same CPU/RAM pool, use the same.NET CLR version, and access the system with the same user identity. A misconfigured app pool can bring an entire Windows server to its knees within minutes by exhausting RAM or spawning zombie processes.

# Create a new app pool
Import-Module WebAdministration

New-WebAppPool -Name 'MyApp_Pool'
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'managedRuntimeVersion' -Value '' # empty for ASP.NET Core
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'enable32BitAppOnWin64' -Value $false

# Idle timeout — default 20 min, 0 (disabled) for 24/7 services
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'processModel.idleTimeout' -Value '00:00:00'

# Recycling — periodic restart as insurance against memory leaks
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'recycling.periodicRestart.time' -Value '1.05:00:00'
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'recycling.periodicRestart.memory' -Value 1572864 # 1.5 GB

# CPU limit (in thousandths — 50000 = 50%)
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'cpu.limit' -Value 50000
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'cpu.action' -Value 'Throttle'

# Identity — ApplicationPoolIdentity is the safest choice
Set-ItemProperty -Path 'IIS:\AppPools\MyApp_Pool' `
 -Name 'processModel.identityType' -Value 'ApplicationPoolIdentity'

# Assign the website to this pool
Set-ItemProperty -Path 'IIS:\Sites\MyApp' `
 -Name 'applicationPool' -Value 'MyApp_Pool'

An important detail: idleTimeout defaults to 20 minutes — on a low-traffic site, the first request wakes the pool and incurs a 5-10 second cold start. For APIs and admin panels that must stay up at all times, set this to zero. On heavily multi-tenant shared servers, however, providers may forbid this setting because it ties up RAM.

Memory and CPU Limits

A periodic restart (e.g., once a day) acts as insurance against memory leaks. A production.NET 8 application is expected to use 200-400 MB of RAM under normal conditions; if it climbs past 1.5 GB, either the load is unusually high or an IDisposable object is leaking. The memory leak diagnosis methods in our Node.js Performance article apply with the same logic to.NET; dotnet-counters and dotnet-dump are your core diagnostic toolkit.

MSSQL Hosting: Working with Microsoft SQL Server

The concept of MSSQL hosting (or web hosting MSSQL) refers to the Microsoft SQL Server database hosting service that almost all Windows hosting packages bundle for free or for a token additional fee. In 2026, providers in Turkey typically offer one of SQL Server 2019 or SQL Server 2022. An important detail: the MSSQL bundled with shared packages is generally Web Edition or Workgroup / Express Edition; full Standard or Enterprise Edition requires a VPS or dedicated package.

SQL Server Editions and Their Limits

  • Express Edition (free): 10 GB per database, 1 GB RAM, and 1 CPU socket (max 4 cores). Sufficient for dev/test and small production.
  • Web Edition: Licensed only for web applications. RAM and CPU limits are close to Standard but licensing is cheap. The version most Windows hosting providers offer in shared packages.
  • Standard Edition: 128 GB RAM, 24 cores. Full BI, Always On Basic Availability Groups, traditional enterprise use.
  • Enterprise Edition: Unlimited RAM and cores, real-time analytics, in-memory OLTP, Always On AG.
  • Developer Edition (free): Feature parity with Enterprise, non-production use only.

When you take a shared MSSQL service, watch for three limits: database size (50 MB - 5 GB on shared packages), concurrent connections (typically 10-100), and log file size (typically 25-100 MB). When any one is exceeded, you'll see The transaction log for database is full or Could not allocate space for object errors. For deeper database tuning, the indexing principles in our SQL Query Optimization and PostgreSQL Performance Optimization articles also apply to MSSQL.

Connection String Patterns

# Classic ASP.NET / Entity Framework — web.config
<connectionStrings>
 <add name="DefaultConnection"
 providerName="System.Data.SqlClient"
 connectionString=
 "Server=tcp:db.example.com,1433;
 Initial Catalog=example_db;
 User ID=example_user;
 Password=StrongPassword_2026!;
 MultipleActiveResultSets=True;
 Encrypt=True;
 TrustServerCertificate=False;
 Connection Timeout=30;
 ApplicationIntent=ReadWrite;" />
</connectionStrings>

# ASP.NET Core appsettings.Production.json
{
 "ConnectionStrings": {
 "DefaultConnection":
 "Server=tcp:db.example.com,1433;Database=example_db;User Id=example_user;Password=StrongPassword_2026!;Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=True;Pooling=True;Min Pool Size=5;Max Pool Size=100;"
 }
}

Three parameters are most often forgotten in production: Encrypt=True (enables TLS, mandatory on shared servers), MultipleActiveResultSets=True (lets Entity Framework run parallel queries on the same connection), and Pooling=True + Max Pool Size (.NET defaults to 100 connections — bump it to 200-300 under heavy traffic). Never commit a connection string to your repo; use dotnet user-secrets, Azure Key Vault, or at the very least appsettings.Production.json + .gitignore.

Remote MSSQL Connection and Firewall

-- Create a new login + user (non-sa)
USE [master];
GO
CREATE LOGIN [example_user]
 WITH PASSWORD = N'StrongPassword_2026!',
 CHECK_POLICY = ON,
 CHECK_EXPIRATION = OFF;
GO

USE [example_db];
GO
CREATE USER [example_user] FOR LOGIN [example_user];
GO

-- Grant only the required privileges — never sa or db_owner
ALTER ROLE db_datareader ADD MEMBER [example_user];
ALTER ROLE db_datawriter ADD MEMBER [example_user];
GRANT EXECUTE ON SCHEMA :: dbo TO [example_user];
GO

-- If the old user is left orphaned
ALTER USER [example_user] WITH LOGIN = [example_user];
GO

-- Monitor active connections
SELECT session_id, login_name, host_name, program_name,
 client_net_address, last_request_start_time
FROM sys.dm_exec_sessions
WHERE is_user_process = 1
ORDER BY last_request_start_time DESC;

On shared Windows hosting, MSSQL is typically provisioned through the Plesk panel, and to connect remotely (from Management Studio) you'll need to be added to the provider's IP allowlist. Some providers disable remote connections entirely — you can only manage the database through a phpMyAdmin-like tool inside the Plesk interface (typically SQL Web Admin or Adminer for MSSQL). On a VPS or dedicated server, you'll need to open TCP/1433 for the sqlservr.exe process in Windows Firewall.

ASP.NET MVC Hosting: Classic MVC 5 vs ASP.NET Core MVC

The query asp net mvc hosting typically refers to two different things, and the distinction is critical. ASP.NET MVC 5 (the System.Web.Mvc namespace) is built on the classic.NET Framework 4.x and runs only on Windows / IIS. ASP.NET Core MVC (the Microsoft.AspNetCore.Mvc namespace) is cross-platform and runs on both Linux and Windows. The two libraries have similar APIs but completely different infrastructure underneath.

  • MVC 5: Global.asax, route definitions in web.config, System.Web.Hosting. Strongly discouraged for new projects, but plenty of existing SMB applications still run on MVC 5.
  • ASP.NET Core MVC: Program.cs, builder.Services.AddControllersWithViews(), dependency injection as a first-class citizen. The only sensible choice for new projects.
  • Hosting requirements: MVC 5 requires Windows + IIS +.NET Framework 4.7.2+. ASP.NET Core MVC just needs the Hosting Bundle + IIS (or Kestrel + Nginx on Linux).
  • Migration effort: An MVC 5 → ASP.NET Core MVC migration is not a 'lift and shift'; controller signatures, model binding, and the filter architecture have changed significantly.
// ASP.NET Core MVC — Program.cs (minimal hosting)
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews()
.AddRazorRuntimeCompilation();

builder.Services.AddDbContext<AppDbContext>(opt =>
 opt.UseSqlServer(
 builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddResponseCompression(opt =>
{
 opt.EnableForHttps = true;
 opt.Providers.Add<BrotliCompressionProvider>();
 opt.Providers.Add<GzipCompressionProvider>();
});

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
 app.UseExceptionHandler("/Home/Error");
 app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseResponseCompression();

app.MapControllerRoute(
 name: "default",
 pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

.NET Core /.NET 5+ Hosting: Kestrel and Cross-Platform

Most developers searching for net core hosting are actually looking for information on modern.NET (versions 5, 6, 7, 8, 9, 10). The.NET Core name was retired in 2020; since then Microsoft has used only the .NET name..NET 8 and.NET 9 are LTS (Long Term Support) releases;.NET 8 support runs through November 2026,.NET 9 through May 2026. Always pick LTS for production.

There are two ways to run a.NET 8/9 app on Windows hosting: framework-dependent deployment (FDD) — assumes the Hosting Bundle is already installed on the server, only your application DLLs are deployed, ~10-30 MB. Self-contained deployment (SCD) — the runtime is packaged with the application and no extra installation is required on the server, but the package size grows to 80-150 MB.

# Framework-dependent deployment (suitable for shared hosting)
dotnet publish -c Release `
 -r win-x64 `
 --no-self-contained `
 -o.\publish

# Self-contained deployment (independent of the provider's runtime)
dotnet publish -c Release `
 -r win-x64 `
 --self-contained true `
 -p:PublishSingleFile=true `
 -p:PublishReadyToRun=true `
 -p:DebugType=embedded `
 -o.\publish

# Zip the publish output and ship it to the server
Compress-Archive -Path.\publish\* `
 -DestinationPath.\app.zip -Force

# Push via Web Deploy (msdeploy.exe required)
& 'C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe' `
 -verb:sync `
 -source:contentPath=.\publish `
 -dest:contentPath='example.com',computerName='https://example.com:8172/msdeploy.axd?site=example.com',userName='deploy_user',password='PasswordXyz',authType='Basic'

Managing Windows Hosting with the Plesk Panel

Almost every Windows shared hosting provider in Turkey ships Plesk as the control panel. cPanel has no official Windows support, which makes Plesk the de facto standard. The main features you'll touch via Plesk: domain management, subdomains and parked domains, FTP/FTPS account creation, Plesk Mail server integration, MSSQL and MySQL database management, SSL certificate provisioning (Let's Encrypt integrated),.NET version selection, IIS application pool control, and the file manager.

.NET Version Selection (via Plesk)

In the Plesk UI, under Websites & Domains → ASP.NET Settings, you can pick the.NET Framework version (2.0, 3.5, 4.x, 4.8) per site, plus the IIS Application Pool settings. ASP.NET Core version is managed through a separate menu (the ASP.NET Core extension shipped with Plesk 18.0.51+). For legacy ASP sites, the Classic ASP option lives under the IIS tab — not under Apache & nginx Settings.

# CLI-based site configuration via Plesk (Windows)
# Plesk directory: C:\Program Files (x86)\Parallels\Plesk

# List all domains
"%plesk_dir%\bin\domain.exe" --list

# Assign.NET 4.8 to a domain
"%plesk_dir%\bin\site.exe" -u example.com `
 -aspnet-version 4.8

# Make the IIS app pool 64-bit
"%plesk_dir%\bin\iis_app_pool.exe" --set example.com `
 -enable32BitOnWin64 false

# Create an MSSQL database in Plesk
"%plesk_dir%\bin\database.exe" --create example_db `
 -domain example.com `
 -server "localhost\MSSQLSERVER" `
 -type mssql `
 -add_user true `
 -new_db_user_login example_user `
 -new_db_user_passwd 'StrongPassword_2026!'

With the Plesk panel you can manage both Windows and Linux hosting from a single interface; that's why Plesk is indispensable for cross-platform hosting providers. For deeper Plesk coverage, see our Plesk Panel Management guide.

SSL Certificates and HTTPS: Plesk + IIS

TLS is essential for the modern web. There are three ways to provision SSL on Windows hosting: Let's Encrypt via Plesk (the easiest and free option), manual certificate import in IIS (with a.pfx file, for purchased certificates), and third-party automated tools like Win-acme or Certify The Web. The Plesk Let's Encrypt extension automatically renews 90-day certificates and makes it easy to add the www subdomain or a wildcard.

# Manual SSL setup on IIS (PFX file)
Import-Module WebAdministration

# 1. Import the PFX into the local machine certificate store
$cert = Import-PfxCertificate `
 -FilePath 'C:\certs\example.com.pfx' `
 -CertStoreLocation 'Cert:\LocalMachine\My' `
 -Password (ConvertTo-SecureString 'PfxPassword' -AsPlainText -Force)

$thumbprint = $cert.Thumbprint

# 2. Create the HTTPS binding
New-WebBinding -Name 'example.com' `
 -Protocol https `
 -Port 443 `
 -HostHeader 'example.com' `
 -SslFlags 1 # SNI enabled

# 3. Attach the certificate to the binding
$binding = Get-WebBinding -Name 'example.com' -Protocol https
$binding.AddSslCertificate($thumbprint, 'My')

# 4. Add the HSTS header in web.config (web.config below)
# <add name="Strict-Transport-Security"
# value="max-age=63072000; includeSubDomains; preload" />

The new IIS shipped with Windows Server 2025 supports HSTS at the system level — you can enable it per-site through Plesk or appcmd. For browser compatibility and modern TLS configuration, see our detailed HTTPS and TLS 1.3 article. Once the certificate is installed, you can verify it with our SSL Certificate Checker tool.

Deployment Strategies: FTP, Web Deploy, GitHub Actions

There are three common ways to deploy to Windows hosting. FTPS is the oldest and most widely supported method; every provider supports it, but constant manual file transfers are extremely error-prone. Web Deploy (msdeploy.exe) is Microsoft's official tool; integration with Visual Studio is excellent, though the provider has to support it (typically over port 8172). A CI/CD pipeline (GitHub Actions, Azure DevOps) is the only sensible choice for enterprise projects — it eliminates manual deployment entirely.

#.github/workflows/deploy-windows-hosting.yml
name: Deploy to Windows Hosting (IIS)
on:
 push:
 branches: [main]

jobs:
 build-deploy:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4

 - name: Setup.NET
 uses: actions/setup-dotnet@v4
 with:
 dotnet-version: '9.0.x'

 - name: Restore + Build
 run: |
 dotnet restore
 dotnet build -c Release --no-restore

 - name: Run unit tests
 run: dotnet test -c Release --no-build --verbosity normal

 - name: Publish (framework-dependent)
 run: |
 dotnet publish./src/MyApp/MyApp.csproj \
 -c Release \
 -r win-x64 \
 --no-self-contained \
 -o./publish

 - name: Deploy via FTPS
 uses: SamKirkland/FTP-Deploy-Action@v4.3.5
 with:
 server: ${{ secrets.FTP_HOST }}
 username: ${{ secrets.FTP_USER }}
 password: ${{ secrets.FTP_PASS }}
 protocol: ftps
 local-dir:./publish/
 server-dir: /httpdocs/
 dangerous-clean-slate: false
 exclude: |
 **/.git*
 **/.github*
 **/logs/**
 **/App_Data/**

For a deeper CI/CD walkthrough see our GitHub Actions CI/CD Guide. If you go with Web Deploy, dropping an app_offline.htm file into the site root during deploy lets IIS shut the application down cleanly and prevents data loss — Microsoft's official IIS Deploy documentation calls this out explicitly.

Performance Tuning: IIS,.NET, and MSSQL

Windows hosting performance is optimized at three layers: HTTP/2 and HTTP/3 at the IIS level, response compression and output caching at the.NET level, indexing and query plan tuning at the MSSQL level. A typical mid-load production site (50-200 requests per second) runs comfortably on a properly configured Windows VPS; on a poorly configured shared host, even 5-10 requests per second can time out.

Enabling HTTP/2 and HTTP/3 on IIS

Windows Server 2016+ supports HTTP/2, and Windows Server 2022+ supports HTTP/3. HTTP/2 is enabled by default for TLS connections; enabling HTTP/3 requires an extra registry tweak. Our Core Web Vitals article walks through the HTTP/2 and HTTP/3 wins in detail.

# Enable HTTP/3 (QUIC) — Windows Server 2022+
New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\HTTP\Parameters' `
 -Name 'EnableHttp3' -Value 1 -PropertyType DWORD -Force

New-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\HTTP\Parameters' `
 -Name 'EnableAltSvc' -Value 1 -PropertyType DWORD -Force

Restart-Service -Name HTTP -Force
iisreset

# Verify — Alt-Svc header
curl -I -k --http3 https://example.com/
# alt-svc: h3=":443"; ma=86400

# IIS dynamic compression
appcmd set config /section:urlCompression `
 /doDynamicCompression:true /doStaticCompression:true

appcmd set config /section:httpCompression `
 /-[name='gzip'] `
 /+[name='gzip',doDynamicCompression='true',
 dynamicCompressionLevel='4',
 staticCompressionLevel='9']

Output Cache and Response Compression

// Response caching middleware in ASP.NET Core
builder.Services.AddResponseCaching(options =>
{
 options.MaximumBodySize = 64 * 1024 * 1024; // 64 MB
 options.UseCaseSensitivePaths = false;
});

// Endpoint-level cache (on a controller action)
[ResponseCache(Duration = 600,
 Location = ResponseCacheLocation.Any,
 VaryByQueryKeys = new[] { "page", "sort" })]
public IActionResult Catalog(int page, string sort)
{
 //...
}

// Output cache (.NET 7+)
builder.Services.AddOutputCache(options =>
{
 options.AddPolicy("Catalog", b =>
 b.Expire(TimeSpan.FromMinutes(10))
.SetVaryByQuery("page", "sort")
.Tag("catalog"));
});

app.UseOutputCache();
app.MapGet("/products", () => GetProducts())
.CacheOutput("Catalog");

MSSQL Query Tuning Fundamentals

-- Find the queries consuming the most CPU
SELECT TOP 20
 qs.total_worker_time / 1000 AS total_cpu_ms,
 qs.execution_count,
 qs.total_worker_time / qs.execution_count / 1000 AS avg_cpu_ms,
 SUBSTRING(qt.text, qs.statement_start_offset / 2 + 1,
 (CASE WHEN qs.statement_end_offset = -1
 THEN DATALENGTH(qt.text)
 ELSE qs.statement_end_offset END
 - qs.statement_start_offset) / 2 + 1) AS query_text,
 qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_worker_time DESC;

-- Missing index recommendations
SELECT TOP 20
 ROUND(s.avg_total_user_cost * s.avg_user_impact
 * (s.user_seeks + s.user_scans), 0) AS index_advantage,
 d.statement AS table_name,
 d.equality_columns,
 d.inequality_columns,
 d.included_columns
FROM sys.dm_db_missing_index_group_stats s
 INNER JOIN sys.dm_db_missing_index_groups g
 ON s.group_handle = g.index_group_handle
 INNER JOIN sys.dm_db_missing_index_details d
 ON g.index_handle = d.index_handle
ORDER BY index_advantage DESC;

-- Add an index (filtered + included)
CREATE NONCLUSTERED INDEX IX_orders_user_active
 ON dbo.orders (user_id, created_at DESC)
 INCLUDE (status, total_amount)
 WHERE status IN ('paid', 'shipped');

Security: IIS Hardening and MSSQL Permissions

Windows hosting packages are not secure by default; no matter how seasoned your provider is, certain hardening steps fall on you. Almost every threat in our OWASP Top 10 2026 article applies equally to IIS /.NET environments.

  • Hide the Server header: Server: Microsoft-IIS/10.0 hands attackers fingerprinting data. Strip it via URL Rewrite + Outbound Rule, or use removeServerHeader.
  • Remove X-Powered-By: in web.config, add <remove name="X-Powered-By" /> inside customHeaders.
  • Disable directory listing: directoryBrowse enabled="false". It's off by default, but verify.
  • Restrict HTTP methods: block unused verbs like TRACE, OPTIONS, and DELETE through request filtering.
  • Limit request size: align maxAllowedContentLength with your upload limit (default is 30 MB; 4 MB is enough for most forms).
  • SQL injection protection: always use parameterized queries or stored procedures. Details: SQL Injection Prevention.
  • Disable the sa account on MSSQL: ALTER LOGIN sa DISABLE. If you need mixed-mode auth, create a strong second admin login.
  • Don't grant db_owner: the application user only needs db_datareader + db_datawriter + EXECUTE.
<!-- Secure web.config baseline -->
<configuration>
 <system.webServer>
 <security>
 <requestFiltering removeServerHeader="true">
 <verbs allowUnlisted="false">
 <add verb="GET" allowed="true" />
 <add verb="POST" allowed="true" />
 <add verb="PUT" allowed="true" />
 <add verb="DELETE" allowed="true" />
 <add verb="HEAD" allowed="true" />
 <add verb="OPTIONS" allowed="true" />
 </verbs>
 <fileExtensions allowUnlisted="true">
 <add fileExtension=".config" allowed="false" />
 <add fileExtension=".cs" allowed="false" />
 <add fileExtension=".csproj" allowed="false" />
 <add fileExtension=".log" allowed="false" />
 </fileExtensions>
 <requestLimits maxAllowedContentLength="31457280" /> <!-- 30 MB -->
 </requestFiltering>
 </security>

 <httpProtocol>
 <customHeaders>
 <remove name="X-Powered-By" />
 <add name="X-Content-Type-Options" value="nosniff" />
 <add name="X-Frame-Options" value="SAMEORIGIN" />
 <add name="Referrer-Policy" value="strict-origin-when-cross-origin" />
 <add name="Permissions-Policy"
 value="camera=(), microphone=(), geolocation=()" />
 <add name="Strict-Transport-Security"
 value="max-age=63072000; includeSubDomains; preload" />
 </customHeaders>
 </httpProtocol>

 <directoryBrowse enabled="false" />
 </system.webServer>
</configuration>

Backups and Disaster Recovery

On Windows hosting you need to back up two distinct things: the file system (web content, configs, logs) and the MSSQL database. Most providers run a weekly backup with 7-30 days of retention — that's not enough. Per our 3-2-1 backup rule, you should keep 3 copies on 2 different media with 1 off-site location.

-- MSSQL full backup (.bak)
BACKUP DATABASE [example_db]
 TO DISK = N'D:\backups\example_db_full_2026-05-02.bak'
 WITH FORMAT, INIT, COMPRESSION,
 MEDIANAME = N'ExampleFullBackup',
 NAME = N'example_db Full Backup',
 STATS = 10;

-- Differential backup (additions on top of the full backup)
BACKUP DATABASE [example_db]
 TO DISK = N'D:\backups\example_db_diff_2026-05-02.bak'
 WITH DIFFERENTIAL, COMPRESSION, INIT, STATS = 10;

-- Transaction log backup (for PITR)
BACKUP LOG [example_db]
 TO DISK = N'D:\backups\example_db_log_2026-05-02_1400.trn'
 WITH COMPRESSION, INIT, STATS = 10;

-- Restore the backup on another server
RESTORE DATABASE [example_db]
 FROM DISK = N'D:\backups\example_db_full_2026-05-02.bak'
 WITH REPLACE, RECOVERY,
 MOVE 'example_db' TO 'D:\Data\example_db.mdf',
 MOVE 'example_db_log' TO 'L:\Logs\example_db.ldf',
 STATS = 10;
# Weekly file backup with Robocopy + an rsync-style remote alternative
robocopy 'C:\inetpub\wwwroot\example.com' `
 '\\backup-server\backup-share\example.com' `
 /MIR /Z /W:5 /R:3 `
 /MT:8 `
 /XD 'logs' 'temp' 'App_Data\Cache' `
 /LOG:C:\backup\robocopy.log

# Auto-prune backups older than 30 days
Get-ChildItem 'D:\backups' -Filter *.bak |
 Where-Object { $_.LastWriteTime -lt (Get-Date).AddDays(-30) } |
 Remove-Item -Force

# rsync-style off-site solution (rclone to S3)
rclone sync D:\backups s3-brand:brand-backups/example.com `
 --transfers 4 --checkers 8 --progress

Windows Hosting Price Ranges in Turkey (2026)

These figures are approximate and vary by provider and seasonal promotion; this is 2026 data. Windows hosting is generally 20-40% more expensive than Linux because Microsoft Windows Server licensing and SQL Server Web/Standard licensing add cost. Local Turkish providers (Turhost, IxirHost, Hosting.com.tr, IHS, Natro, LimonHost, Odeaweb, GuzelHosting, etc.) typically position their Windows hosting packages in similar price brackets.

  • Entry packages (1 site, 1-5 GB disk, 1 GB RAM, 1 MSSQL database): around ₺70-120/month (roughly $2-4 USD).
  • Mid-tier packages (3-5 sites, unlimited disk, 2 GB RAM, 5+ MSSQL databases): around ₺120-200/month (roughly $4-7 USD).
  • Professional packages (10 sites, 4-8 GB RAM, 2-4 vCPU, unlimited MSSQL): around ₺200-350/month (roughly $7-12 USD).
  • Premium / Unlimited (unlimited sites, 8 GB+ RAM, 4 vCPU): around ₺300-500/month (roughly $10-17 USD).
  • Windows VPS (your own RDP, full administrator access, your own MSSQL Standard license): around ₺500-2,500/month (roughly $17-85 USD; depends on RAM/CPU/disk).
  • Dedicated Windows server (physical machine): ₺5,000-25,000+/month (roughly $170-850+ USD; depends on hardware and any MSSQL Enterprise license).

One line item to watch carefully: the SQL Server Standard / Enterprise license. When you rent a VPS, the Windows Server license is typically included, but the MSSQL license is sold separately. Standard Edition runs roughly $7,000-9,000 USD per core per year; that's why many developers stay on Express Edition or pick a VPS provider that's licensed under the SPLA (Service Provider Licensing Agreement).

Windows Hosting vs VPS vs Cloud (Azure App Service)

For a production environment, choosing between Windows hosting, VPS, and cloud is both a technical and a cost decision. Our VPS Hosting Guide covers it from a Linux angle, but the principles are identical.

  • Shared Windows hosting: Sufficient for the WordPress +.NET corporate-site mix on low traffic (< 10K requests/day). No RDP, no direct IIS access — administration only via the Plesk panel.
  • Windows VPS: 100K-1M requests/day, ideal when you want to run your own IIS configuration. RDP access, full admin rights, access to performance counters. Providers like our brand offer Windows VPS in Turkey.
  • Dedicated Windows server: 1M+ requests/day, MSSQL Enterprise + Always On AG, multi-tenant SaaS applications. CPU and RAM dedicated entirely to you.
  • Azure App Service for Windows: Microsoft's managed platform. Auto-scaling, slot deployments, automated SSL. Expensive but with zero operations overhead. Official reference: dotnet.microsoft.com/apps/aspnet/hosting.
  • AWS EC2 Windows + RDS SQL Server: Multi-region enterprise architecture. Lambda +.NET 8 gives you a serverless option. Costs ramp up fast, but it's a strong alternative to Azure.
  • Container approach: Running.NET 8 in a Linux container is dramatically cheaper and faster than a Windows container. For everything but legacy MVC 5 / Web Forms applications, new projects almost always pick Linux + Docker.

Our Deploying Applications with Docker and Kubernetes Basics articles are the foundational resources for running.NET apps in containers. Microsoft's official mcr.microsoft.com/dotnet/aspnet:9.0 image is under 100 MB and is Linux + Alpine-based.

Logging and Monitoring: stdout, Event Log, ETW

Windows hosting gives you log collection at three layers: ASP.NET Core application logs (stdout or Serilog), IIS access and error logs, and the Windows Event Log. For effective debugging, you need to be able to read all three.

// Structured logging with Serilog — Program.cs
using Serilog;
using Serilog.Sinks.MSSqlServer;

var builder = WebApplication.CreateBuilder(args);

builder.Host.UseSerilog((ctx, services, loggerCfg) =>
{
 loggerCfg
.ReadFrom.Configuration(ctx.Configuration)
.MinimumLevel.Information()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithProperty("Application", "ExampleApi")
.WriteTo.Console()
.WriteTo.File(
 path: "logs/app-.log",
 rollingInterval: RollingInterval.Day,
 retainedFileCountLimit: 30)
.WriteTo.MSSqlServer(
 connectionString: ctx.Configuration
.GetConnectionString("DefaultConnection"),
 sinkOptions: new MSSqlServerSinkOptions
 {
 TableName = "AppLogs",
 AutoCreateSqlTable = true,
 BatchPostingLimit = 50
 });
});

IIS access logs are kept by default in C:\inetpub\logs\LogFiles\W3SVC{N}\ in W3C format; they rotate daily and are not compressed. Our ELK Stack Log Analysis article details the Filebeat → Logstash → Elasticsearch pipeline; on Windows you can also use winlogbeat to collect Event Log entries.

# Pull application errors from the Event Log over the last 24 hours
Get-WinEvent -FilterHashtable @{
 LogName = 'Application'
 Level = 1, 2, 3 # Critical, Error, Warning
 StartTime = (Get-Date).AddHours(-24)
} | Where-Object { $_.ProviderName -like '*ASP.NET*' } |
 Select-Object TimeCreated, LevelDisplayName, Message |
 Format-Table -AutoSize

# Tail-style live IIS access log
Get-Content -Path 'C:\inetpub\logs\LogFiles\W3SVC1\u_ex*.log' `
 -Tail 50 -Wait

# Measure the 5xx error rate by hour
Get-ChildItem 'C:\inetpub\logs\LogFiles\W3SVC1' -Filter '*.log' |
 ForEach-Object {
 Get-Content $_ |
 Where-Object { $_ -match '\s(5\d{2})\s' } |
 Measure-Object
 }

PHP, Node.js, and Other Languages on Windows Hosting

Windows hosting isn't limited to.NET. Most modern Windows hosting packages can run PHP 7.x and 8.x (via FastCGI), Node.js (via the iisnode module or HttpPlatformHandler reverse proxy), Python (HttpPlatformHandler), and even Ruby on Rails. Performance-wise, however, the natural runtime for these languages is Linux — the same application can run 15-30% slower on Windows.

<!-- Run a Node.js application behind IIS via HttpPlatformHandler -->
<configuration>
 <system.webServer>
 <handlers>
 <add name="httpPlatformHandler"
 path="*" verb="*"
 modules="httpPlatformHandler"
 resourceType="Unspecified" />
 </handlers>

 <httpPlatform processPath="node"
 arguments="server.js"
 startupTimeLimit="30"
 startupRetryCount="3"
 stdoutLogEnabled="true"
 stdoutLogFile=".\logs\node-stdout.log">
 <environmentVariables>
 <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
 <environmentVariable name="NODE_ENV" value="production" />
 </environmentVariables>
 </httpPlatform>
 </system.webServer>
</configuration>

For PHP sites, concepts such as LSCache, WordPress SEO plugins, and cPanel don't map directly to the Windows side; the equivalents are Plesk's Cache Manager and a PHP-FPM-style FastCGI pool. Running WordPress on Windows is technically possible but not recommended for performance and plugin compatibility — WordPress is already optimized for Linux + Apache/Nginx + MySQL.

Common Errors and Quick Fixes

  • HTTP 500.30 - ASP.NET Core app failed to start: Turn on the stdout log (stdoutLogEnabled="true"); usually a connection string error, a missing DLL, or a.NET runtime version mismatch.
  • HTTP 500.19 - Internal Server Error from web.config: An XML error in web.config or a missing IIS module (URL Rewrite, ASP.NET Core Module). Check %windir%\system32\inetsrv\config\applicationHost.config.
  • HTTP 502.5 - Process failed to start: Hosting Bundle is missing, the wrong version is installed, or the app pool.NET version is wrong (must be No Managed Code for Core).
  • HTTP 503 - Service Unavailable: The app pool is stopped or stuck in a recycle loop. Check Event Viewer → Windows Logs → Application.
  • SQL connection timeout: Bump Connection Timeout=30, but most of the time the real cause is the firewall, a wrong instance name, or the MSSQL TCP/IP protocol being disabled (enable it from SQL Server Configuration Manager).
  • The transaction log is full: Drain it with BACKUP LOG, or switch the recovery model to SIMPLE (if you don't need PITR).
  • Could not load file or assembly: A DLL is missing in the bin/ folder; verify that you deployed the publish output correctly.
  • The page cannot be displayed because an internal server error has occurred: Set customErrors mode="Off" to see the actual error; turn it back on afterward.

FAQ: Frequently Asked Questions about Windows Hosting

Is Windows hosting slower than Linux hosting?

On the same hardware, Linux-native technologies like PHP/Node.js do run 15-30% slower on Windows. But.NET / ASP.NET applications can run marginally faster on Windows + IIS than on Linux + Kestrel (especially with in-process hosting). So performance is not abstract — it depends on the technology you're running.

Should I use Windows hosting for WordPress?

No. WordPress is part of the MySQL, PHP, and Apache/Nginx ecosystem; even if it runs on Windows, plugin compatibility and performance always trail Linux. For WordPress, pick Linux hosting alongside LSCache.

Can I get away with MSSQL Express?

If your database is under 10 GB, you have fewer than 50 concurrent users, and you don't need advanced features (Always On, Service Broker, In-Memory OLTP), yes. Express is completely free and is enough for 80% of SMB applications.

Should I deploy my ASP.NET Core app to Linux or Windows?

For a brand-new project with no Windows-specific dependencies (Active Directory integration, COM+ components, Windows Performance Counters), Linux + Docker + Kubernetes is cheaper and more flexible. If you're migrating an existing Windows application, staying on Windows hosting reduces deploy complexity.

Can I get an RDP-enabled VPS instead of Plesk + Windows hosting?

Yes, but the management overhead grows considerably. SSL setup, FTP account creation, DNS updates that take minutes through Plesk can take 30-60 minutes over RDP. If you're routinely managing multiple sites / domains / mailboxes, the Plesk license fee pays for itself.

Does WebSocket work on Windows hosting?

Yes. IIS 8.0+ supports WebSocket natively. For SignalR or raw WebSocket, the WebSocket role must be enabled under Windows Features. Our WebSocket vs SSE article walks through which to pick in which scenario.

Migration Scenarios: Linux to Windows Hosting and Back

Migrating an existing site from Linux to Windows (or vice versa) is rarely just a file copy. For PHP sites, .htaccess rules have to be translated by hand into web.config URL Rewrite rules; $_SERVER['REQUEST_URI'] behavior, the path separator (/ vs \), and realpath() results can all differ.

<!-- Example of translating Apache.htaccess RewriteRules into web.config -->
<!--.htaccess: -->
<!-- RewriteEngine On -->
<!-- RewriteCond %{REQUEST_FILENAME} !-f -->
<!-- RewriteCond %{REQUEST_FILENAME} !-d -->
<!-- RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] -->

<configuration>
 <system.webServer>
 <rewrite>
 <rules>
 <rule name="PHP Front Controller" stopProcessing="true">
 <match url="^(.*)$" />
 <conditions logicalGrouping="MatchAll">
 <add input="{REQUEST_FILENAME}" matchType="IsFile"
 negate="true" />
 <add input="{REQUEST_FILENAME}" matchType="IsDirectory"
 negate="true" />
 </conditions>
 <action type="Rewrite" url="index.php?url={R:1}" appendQueryString="true" />
 </rule>
 </rules>
 </rewrite>
 </system.webServer>
</configuration>

An MSSQL → MySQL move (or the reverse) is in a different category entirely — schema differences (NVARCHAR vs VARCHAR, UNIQUEIDENTIFIER vs BINARY(16), BIT vs TINYINT), index syntax differences, and rewriting the stored procedure language (T-SQL vs PL/SQL). Our MySQL vs PostgreSQL article details the data-model differences; the same principles apply when comparing against MSSQL.

Advanced Topics: Windows Containers, IIS Workers, ETW Tracing

Windows Containers (notably the Server Core-based mcr.microsoft.com/windows/servercore/iis image) let you package classic IIS apps with Docker. The upside: you can run on Kubernetes (with Windows nodes), manage with Helm charts, and do blue/green deploys. The downside: image sizes of 5-10 GB and 30-60 second startup times (vs 1-3 seconds for Linux containers). For new projects, Linux containers +.NET 9 are always the better choice.

# Dockerfile — Windows IIS +.NET Framework 4.8
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8-windowsservercore-ltsc2022

WORKDIR /inetpub/wwwroot
COPY./publish/./

# IIS app pool.NET version
RUN powershell -Command \
 Import-Module WebAdministration; \
 Set-ItemProperty IIS:\AppPools\DefaultAppPool \
 -Name managedRuntimeVersion -Value 'v4.0'

EXPOSE 80

# Health check
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
 CMD powershell -command \
 try { \
 $r = iwr http://localhost/health -UseBasicParsing -TimeoutSec 2; \
 if ($r.StatusCode -eq 200) { exit 0 } else { exit 1 } \
 } catch { exit 1 }

ETW (Event Tracing for Windows) is the most powerful tool for.NET / IIS performance profiling. PerfView, dotnet-trace, and the Visual Studio Profiler all use ETW sessions. You can only diagnose deep issues like CPU bottlenecks, GC pauses, and lock contention with ETW. Our OpenTelemetry Distributed Tracing article covers modern observability principles;.NET 9 has first-class OpenTelemetry support.

Which Industries Still Use Windows Hosting?

A significant slice of the enterprise software ecosystem is wedded to the Microsoft stack. As of 2026, the heaviest users of Windows hosting are:

  • Banking and insurance: Windows bridges to legacy COBOL/AS400 applications, card transaction history kept in MSSQL.
  • Government and state-owned enterprises: Official institutions that integrate with e-Government services and run primarily ASP.NET applications.
  • Manufacturing / ERP: ERP products like SAP, Microsoft Dynamics, and Logo Tiger run under Windows.
  • Healthcare: Most hospital information management systems (HIMS) are built on.NET + MSSQL.
  • Education: National e-school platforms and university student information systems.
  • Engineering / CAD: AutoCAD and SolidWorks license servers.
  • Construction / contracting: Building inspection and progress payment tracking software.

In these sectors, a typical enterprise customer hosts at least 3-5 ASP.NET applications on a shared Windows host or VPS. Migration difficulty and regulatory constraints mean these applications won't move to Linux for another 5-15 years, and Windows hosting demand isn't shrinking in the short term.

Quick Start Checklist

Steps to take a fresh Windows hosting package from initial setup to production:

  • 1. Sign in to the Plesk panel — replace the provider screen and the temporary password.
  • 2. Add the domain and point the DNS A/AAAA records. DNS Guide.
  • 3. Enable Let's Encrypt SSL — the Plesk extension does it in one click. Let's Encrypt Setup.
  • 4. Add the HTTP → HTTPS redirect in web.config.
  • 5. Create an FTPS user and disable plain FTP.
  • 6. Create the MSSQL database and grant a non-sa user db_datareader + db_datawriter.
  • 7. Pick the right.NET version (Plesk → ASP.NET Settings).
  • 8. Verify the application pool: 64-bit, with an appropriate idleTimeout.
  • 9. Apply web.config security headers (HSTS, CSP, X-Content-Type-Options).
  • 10. First deploy — via FTPS or GitHub Actions.
  • 11. Configure a weekly off-site backup in Plesk Backup Manager.
  • 12. Set up uptime monitoring (UptimeRobot or similar).

Resources and Further Reading

Get professional support for Windows hosting, IIS configuration, and MSSQL setup

For installation, deployment, performance tuning, and 24/7 monitoring services that keep your ASP.NET Core and classic MVC applications running smoothly on Windows, get in touch

WhatsApp