sql server hub / upgrade guide

SQL Serverupgrade guide

Upgrade work is only finished when the version is supported, the workload still behaves correctly, and rollback has been tested.

Use this guide to check version and edition details, compatibility levels, dependencies, backups, Query Store, test run output, and post-upgrade behavior before the production window.

version path

compatibility

rollback

Guide

Guide~10 min readUpdated 19 Apr 2026

Share

LinkedInXEmail

Use this when

The version change needs a real validation plan

1

Confirm the current build, edition, operating system, and supported target path.

2

Keep the engine upgrade separate from compatibility-level changes unless testing says otherwise.

3

Test backup, restore, CHECKDB, rollback, jobs, and application validation before the window.

4

Use Query Store, waits, errors, and business workflows to check behavior after the upgrade.

1 / Upgrade result

What SQL Server upgrades must validate

A SQL Server upgrade must validate more than setup completion. The target version has to be supported, the databases have to open cleanly, jobs and integrations need to work, and important queries must keep acceptable plans.

Treat compatibility level, drivers, linked servers, Query Store, SQL Agent jobs, backups, monitoring, and application checks as part of the upgrade. If any of those are left out, the outage window can finish with the instance online but the service still broken.

LayerWhat it answers
Version pathWhether the current instance can move to the target version and edition directly.
Database behaviorWhether compatibility level, plans, and database scoped settings are understood.
DependenciesWhether jobs, linked servers, credentials, drivers, and applications still work.
RollbackWhether the return path is tested inside the real outage window.

2 / Version

Check current version, edition, and patch level

Start with the exact source version. Edition, build, product level, operating system, installed features, and target version decide whether this is an in-place upgrade, side-by-side migration, or rebuild.

Microsoft supported-version tables should be checked before planning the method. Older sources may need a migration path instead of a direct setup upgrade.

Current SQL Server version and edition

Reads instance version, edition, build, update level, and the full version string.

SELECT
    SERVERPROPERTY('MachineName') AS machine_name,
    SERVERPROPERTY('ServerName') AS server_name,
    SERVERPROPERTY('InstanceName') AS instance_name,
    SERVERPROPERTY('Edition') AS edition,
    SERVERPROPERTY('ProductVersion') AS product_version,
    SERVERPROPERTY('ProductLevel') AS product_level,
    SERVERPROPERTY('ProductUpdateLevel') AS product_update_level,
    SERVERPROPERTY('ProductBuild') AS product_build,
    SERVERPROPERTY('EngineEdition') AS engine_edition,
    @@VERSION AS version_string;

ProductVersion and ProductBuild identify the exact source build. Edition affects upgrade rights, feature availability, and target-edition planning. ProductUpdateLevel helps compare the instance with the intended patch baseline. Use this output with Microsoft supported upgrade path documentation before selecting the method.

3 / Path

Choose the upgrade path

In-place upgrade changes the existing instance. Side-by-side upgrade builds a new target and moves databases, jobs, logins, and connection strings. The right choice depends on rollback needs, outage tolerance, age of the source, operating system support, and how much cleanup is needed.

If the source is too old for a direct path, or the server needs a platform change, use a migration plan rather than forcing the upgrade into the old host.

PathUse it when
In-place upgradeThe source is supported, rollback is planned, the host is healthy, and the outage window can absorb the work.
Side-by-side upgradeRollback matters, the host is old, dependencies need cleanup, or the move needs a cleaner target.
MigrationThe work includes host, storage, cloud, architecture, or instance redesign.
RebuildThe current installation is messy enough that keeping it would carry old problems forward.

4 / Compatibility

Review database compatibility levels

Engine version and database compatibility level are separate decisions. Keeping the old compatibility level can reduce behavior changes during the engine upgrade, while a later compatibility-level change can unlock newer optimizer behavior after testing.

Query Store should be ready before compatibility changes. It gives you a better chance of finding plan regressions and comparing important queries before and after the change.

Database compatibility levels

Lists user databases with compatibility level, recovery model, state, read-only flag, and Query Store flag.

SELECT
    d.name AS database_name,
    d.compatibility_level,
    d.recovery_model_desc,
    d.state_desc,
    d.is_read_only,
    d.is_query_store_on,
    d.create_date
FROM sys.databases AS d
WHERE d.name NOT IN (N'master', N'model', N'msdb', N'tempdb')
ORDER BY d.compatibility_level, d.name;

compatibility_level shows which databases may retain older behavior after the engine upgrade. is_query_store_on helps decide whether plan comparison is ready. Read-only or offline databases need separate handling. Do not change compatibility levels until the workload has been tested.

Database scoped configuration review

Run inside each important database to check optimizer-related database scoped settings.

SELECT
    DB_NAME() AS database_name,
    configuration_id,
    name,
    value,
    value_for_secondary
FROM sys.database_scoped_configurations
WHERE name IN (
    N'LEGACY_CARDINALITY_ESTIMATION',
    N'QUERY_OPTIMIZER_HOTFIXES',
    N'PARAMETER_SNIFFING',
    N'MAXDOP'
)
ORDER BY name;

LEGACY_CARDINALITY_ESTIMATION can explain why a database behaves differently from the engine default. QUERY_OPTIMIZER_HOTFIXES may affect plan behavior after version changes. PARAMETER_SNIFFING and MAXDOP settings should be understood before blaming the upgrade. Record settings before the upgrade so changes can be explained later.

Compatibility-level change template

Non-executing template for a planned compatibility-level change after workload testing.

-- Template only. Change compatibility level after testing the workload.
-- Do not combine this with the engine upgrade unless it is part of the tested plan.

ALTER DATABASE [YourDatabase] SET COMPATIBILITY_LEVEL = 160;

Use the target level for the installed SQL Server version. Run this only after testing important queries and application workflows. Keep Query Store available so plan changes can be reviewed. Treat this as a separate change when the upgrade window is already tight.

5 / Feature risk

Find deprecated and removed feature risk

Version upgrades can expose old syntax, discontinued components, unsupported features, driver limits, and application code that assumed older behavior. Review Microsoft deprecated and breaking-change notes for the source and target versions.

Use Microsoft Data Migration Assistant, vendor support notes, and application tests to find problems before the outage window. The important output is a list of blockers, required code changes, and accepted risks.

InputWhat to check
Microsoft upgrade notesSupported source versions, target edition, removed features, and special upgrade steps.
Data Migration AssistantCompatibility issues, deprecated feature usage, and blockers found by assessment.
Vendor support matrixApplication, driver, SSIS, reporting, and third-party tool support for the target version.
Application testsLogin, search, reports, batch jobs, integrations, and month-end workflows.

6 / Dependencies

Check jobs, linked servers, drivers, and dependencies

SQL Server can upgrade successfully while scheduled work, linked servers, credentials, reports, or application connections fail. Dependency checks need to happen before and after the upgrade.

Keep application owners involved for driver versions, connection strings, vendor support, and smoke tests. SQL output alone cannot validate external behavior.

SQL Agent job history

Shows recent SQL Agent job steps, runtime, status, and messages.

SELECT TOP (100)
    j.name AS job_name,
    j.enabled,
    h.step_id,
    h.step_name,
    h.run_status,
    DATETIMEFROMPARTS(
        h.run_date / 10000,
        (h.run_date % 10000) / 100,
        h.run_date % 100,
        h.run_time / 10000,
        (h.run_time % 10000) / 100,
        h.run_time % 100,
        0
    ) AS run_start_time,
    ((h.run_duration / 10000) * 3600)
      + (((h.run_duration % 10000) / 100) * 60)
      + (h.run_duration % 100) AS run_duration_seconds,
    h.message
FROM msdb.dbo.sysjobs AS j
LEFT JOIN msdb.dbo.sysjobhistory AS h
    ON h.job_id = j.job_id
WHERE h.run_date >= CONVERT(int, CONVERT(char(8), DATEADD(day, -14, SYSDATETIME()), 112))
ORDER BY run_start_time DESC, j.name, h.step_id;

run_status identifies failed or retrying steps. run_duration_seconds helps find jobs that may not fit the upgrade window. message can show path, permission, package, or command problems. Use this before upgrade test run and again after cutover.

Dependency inventory starting point

Counts common server-level dependencies that often affect upgrade and side-by-side moves.

SELECT
    N'Linked servers' AS dependency_type,
    COUNT(*) AS item_count,
    STRING_AGG(CONVERT(nvarchar(max), s.name), N'; ') AS sample_items
FROM sys.servers AS s
WHERE s.is_linked = 1

UNION ALL

SELECT
    N'Credentials' AS dependency_type,
    COUNT(*) AS item_count,
    STRING_AGG(CONVERT(nvarchar(max), c.name), N'; ') AS sample_items
FROM sys.credentials AS c

UNION ALL

SELECT
    N'Enabled SQL Agent jobs' AS dependency_type,
    COUNT(*) AS item_count,
    STRING_AGG(CONVERT(nvarchar(max), j.name), N'; ') AS sample_items
FROM msdb.dbo.sysjobs AS j
WHERE j.enabled = 1

UNION ALL

SELECT
    N'Server triggers' AS dependency_type,
    COUNT(*) AS item_count,
    STRING_AGG(CONVERT(nvarchar(max), tr.name), N'; ') AS sample_items
FROM sys.server_triggers AS tr
WHERE tr.is_disabled = 0;

Linked servers may need provider, login, network, and encryption checks. Credentials can affect jobs, backups, proxies, and external access. Enabled SQL Agent jobs need ownership and post-upgrade validation. Server triggers and other server-level objects should be documented before the window.

7 / Test run

Test backup, restore, CHECKDB, and rollback

A test run should measure the full path: final backups, restore test, CHECKDB, upgrade steps, application validation, job checks, monitoring checks, and rollback. A plan that only covers setup does not cover the service.

Rollback must be tested against the real timing. If the old instance cannot be returned inside the outage window, that is not a rollback plan; it is a rebuild plan.

Backup readiness before upgrade

Shows latest full, differential, and log backups for each database before the upgrade window.

WITH LastBackups AS (
    SELECT
        bs.database_name,
        bs.type,
        MAX(bs.backup_finish_date) AS last_backup_finish_date
    FROM msdb.dbo.backupset AS bs
    WHERE bs.type IN ('D', 'I', 'L')
    GROUP BY bs.database_name, bs.type
)
SELECT
    d.name AS database_name,
    d.recovery_model_desc,
    d.state_desc,
    MAX(CASE WHEN lb.type = 'D' THEN lb.last_backup_finish_date END) AS last_full_backup,
    MAX(CASE WHEN lb.type = 'I' THEN lb.last_backup_finish_date END) AS last_differential_backup,
    MAX(CASE WHEN lb.type = 'L' THEN lb.last_backup_finish_date END) AS last_log_backup
FROM sys.databases AS d
LEFT JOIN LastBackups AS lb
    ON lb.database_name = d.name
WHERE d.name <> N'tempdb'
GROUP BY d.name, d.recovery_model_desc, d.state_desc
ORDER BY d.name;

last_full_backup is the minimum starting point for rollback and restore testing. last_log_backup matters for databases in full or bulk-logged recovery model. state_desc should be understood before the window starts. If backup coverage is weak, fix that before testing the upgrade.

CHECKDB validation template

Non-executing template for planned integrity checks before and after the upgrade test run.

-- Template only. Schedule this where the runtime and I/O load are acceptable.
-- Run before and after the upgrade test run, and record the output.

DBCC CHECKDB (N'YourDatabase') WITH NO_INFOMSGS;

CHECKDB can be resource-heavy; schedule it deliberately. Run it against restored copies when production impact is a concern. Record output before and after the test run. Do not use the upgrade window as the first time this command is tried.

8 / Validation

Validate Query Store, plans, waits, and workload behavior

Post-upgrade validation needs technical checks and business checks. SQL Server may be online while important queries regress, scheduled jobs fail, monitoring breaks, or application workflows return different results.

Query Store, waits, SQL Agent output, error logs, monitoring data, and selected application workflows should all feed the go or no-go decision.

Query Store status

Run inside each important database to confirm Query Store state, storage, capture mode, and cleanup settings.

SELECT
    DB_NAME() AS database_name,
    actual_state_desc,
    desired_state_desc,
    readonly_reason,
    current_storage_size_mb,
    max_storage_size_mb,
    query_capture_mode_desc,
    size_based_cleanup_mode_desc,
    stale_query_threshold_days
FROM sys.database_query_store_options;

actual_state_desc should be READ_WRITE for useful capture. readonly_reason explains why Query Store may not be collecting data. current_storage_size_mb near max_storage_size_mb can stop useful capture. Check this before and after upgrade or compatibility-level changes.

Query Store workload starting point

Lists high-duration Query Store entries as a starting point for before-and-after comparison.

SELECT TOP (50)
    qt.query_sql_text,
    q.query_id,
    p.plan_id,
    rs.count_executions,
    CAST(rs.avg_duration / 1000.0 AS decimal(18,2)) AS avg_duration_ms,
    CAST(rs.avg_cpu_time / 1000.0 AS decimal(18,2)) AS avg_cpu_ms,
    CAST(rs.avg_logical_io_reads AS decimal(18,2)) AS avg_logical_reads,
    rs.last_execution_time
FROM sys.query_store_runtime_stats AS rs
JOIN sys.query_store_plan AS p
    ON p.plan_id = rs.plan_id
JOIN sys.query_store_query AS q
    ON q.query_id = p.query_id
JOIN sys.query_store_query_text AS qt
    ON qt.query_text_id = q.query_text_id
ORDER BY rs.avg_duration DESC;

avg_duration_ms and avg_cpu_ms show candidates for comparison. avg_logical_reads helps find queries with plan or access-path sensitivity. last_execution_time confirms whether the query still matters recently. Use this with application context, not as a standalone blame list.

9 / Do not guess

What not to change blindly

Upgrade windows punish extra changes. Keep the work focused, measured, and reversible wherever possible.

1

Do not treat setup success as upgrade validation.

2

Do not change compatibility level during the engine upgrade unless it was tested.

3

Do not combine the upgrade with unrelated cleanup.

4

Do not skip backup, restore, and rollback testing.

5

Do not promise rollback unless it fits inside the real outage window.

6

Do not ignore SQL Agent jobs, linked servers, drivers, vendor support, SSIS, reporting, and application connection strings.

7

Do not judge post-upgrade performance from CPU alone; check Query Store, waits, plans, errors, and business-critical workflows.

8

Do not use production as the first full test run.

10 / Upgrade support

When to request upgrade support

Upgrade support makes sense when the source version is old, the upgrade path is not direct, compatibility-level behavior is unclear, rollback has not been tested, or important applications need a clean validation plan.

Send version output, target version, edition, operating system, database list, compatibility levels, Query Store status, job history, backup history, dependency list, outage window, and the main reason for the upgrade.

Next step

If the upgrade path, compatibility-level plan, or rollback testing is not ready yet, use the SQL Server upgrade support page or request help above.

Next useful reads: the SQL Server update guide for patch planning, the live updates tracker for current servicing context, the SQL Server migration guide for host moves, the SQL Server backup guide for rollback inputs, and the SQL Server monitoring guide for post-upgrade checks.