Search This Blog

Thursday, October 29, 2026

SQL Server 2016 Has Reached End of Support. Now What?

SQL Server 2016 Has Reached End of Support. Now What?

On July 14, 2026, SQL Server 2016 reached the end of extended support. That means regular security updates are over (unless you have Extended Security Updates (ESUs) in place), and the product is no longer in Microsoft's normal support lifecycle.

But if you still had a SQL Server 2016 instance running that morning, nothing catastrophic happened. It did not crash, the SQL server keeps doing its job, even though the security and support risks have changed underneath it.

See Microsoft Article:  SQL Server 2016 end of support is here: Plan your next steps

I'm not going to walk through how to upgrade. There are already plenty of good guides for that. What I want to talk about is the part that usually gets less attention: the decisions you're left with when SQL Server 2016 is still sitting in production. 

  • Why is it still there? 
  • Do you actually know where all of it is? 
  • How long can it stay, and what will that cost? 
  • What do you do when it can't move yet, or when it is managed by another team or a vendor instead of you? 
  • And what happens if upgrading the SQL Server instance while leaving the database at its existing compatibility level, as SQL Server does by default, isn’t enough?

Here are the dates worth keeping in mind as you read:

Milestone Date
SQL Server 2016 extended support ended July 14, 2026
Windows Server 2016 extended support ends January 12, 2027
SQL Server 2016 ESU Year 1 ends July 13, 2027
SQL Server 2016 ESU Year 2 ends July 18, 2028
SQL Server 2016 ESU Year 3 ends (final) July 17, 2029

These dates are from Microsoft's SQL Server 2016 lifecycle page, and the Windows Server date from the Windows Server 2016 lifecycle page.

Four Releases Later, There Is a Reason

Since SQL Server 2016 was released, Microsoft has shipped four major releases: 2017, 2019, 2022, and, most recently, SQL Server 2025. That means a database still running on SQL Server 2016 has stayed put through four potential upgrade cycles. I'll be honest: I still have a few SQL Server 2014 servers myself, though I've finally said goodbye to 2012 and 2008. So I'm not here to judge. Every one of those servers is still around for a reason, even if it's not always a good reason.

It probably did not happen by accident. Something technical, contractual, operational, or organizational has kept it there. Sometimes, those reasons are entirely legitimate.

  • The vendor may have certified its application only on SQL Server 2016, and running it on anything newer voids your support. 
  • The application may be scheduled for retirement, so nobody wants to spend money upgrading a system that's on its way out.  I'm living this one right now. Some of my SQL Server 2016 servers support an application that's "eventually" going to be replaced by a different one, and if you've been around long enough, you know how much weight "eventually" can carry. Others are genuinely scheduled for retirement in the near future. Both are perfectly reasonable reasons not to upgrade. But either way, I end up in the same predicament: an unsupported SQL Server in production.
  • The workload might depend on a feature that was later removed, for example PolyBase with Hadoop (HDFS) data sources, which aren't supported in SQL Server 2022 and later.
  • The system lives under regulatory or validation requirements that make any platform change expensive to re-certify.

Other times, the reasons are harder to defend:

  • No one clearly owns the application, so no one has the authority or accountability to approve a change.
  • “If it ain’t broke, don’t fix it”. 
  • The developers who built the application moved on years ago, and no one is quite sure what an upgrade might break.
  • The upgrade was never considered important enough. It kept losing out to work that felt more urgent, every quarter, for years.

Be honest about the reasons. A genuine reason needs a plan built around it.  An excuse mostly needs an owner and a deadline to get that database on a supported version as quickly as possible.

Start With the Instances Nobody Knows About

Everything else in this article assumes you know where your SQL Server 2016 instances are. In a large or long-lived environment, believe me, that is not so simple.

The instances on your monitoring dashboard are usually the easy ones. The ones that keep me up at night are the ones that never made it into an inventory, monitoring tool, or ownership list.

You probably know the type. 

  • There's the Express edition that some application quietly installed as part of its own setup, which nobody thinks of as a "real" SQL Server.  Some DBA teams even treat Express edition as outside their scope, leaving it out of their patching, monitoring, and backup routines.. 
  • There's the test server someone built for a project years ago and never shut down. There's the server a business unit or contractor stood up on their own without ever looping in the DBA team. 
  • There are laptops and workstations running a local instance for some desktop app or reporting tool. 
  • And there are the leftovers: servers that were repurposed, where SQL Server stayed installed long after the original application moved on.

These instances matter for two reasons. First, they tend to be the least hardened and least monitored machines you have, which makes them an attractive way in for an attacker. Second, many of them can't be covered by Extended Security Updates even if someone is willing to pay, because Microsoft lists only Enterprise and Standard editions as eligible, other editions are explicitly excluded from receiving ESUs Extended Security Updates FAQs.

Finding Them

There is no single tool that finds everything, so it pays to approach the problem from several directions.

A good starting point is the free dbatools PowerShell module. Its Find-DbaInstance command (from dbatools) combines Active Directory service principal name (SPN) lookups, the same instance browsing SSMS uses, IP range scans, and TCP port checks, and it tells you how confident it is about each result. One friendly piece of advice: give your network and security teams a heads-up before you start scanning subnets. To their monitoring tools, a scan can look an awful lot like an attack, and that's not a question you want to be answering after the fact. Just yesterday, I received an instant message from a cybersecurity analyst asking what I was working on. In his words: "You are lighting up CrowdStrike."

Azure Arc can help, too. When an eligible server is connected to Azure Arc, SQL Server instances on that server are normally registered automatically unless automatic deployment has been disabled with a tag. That gives you a useful inventory you can query across the environment, including questions such as, “How many SQL Server 2016 instances do we have?”

The catch is that Azure Arc can only report on servers already connected to it. It will not find the server nobody knows about. Treat Arc as one source among several, not the complete answer.

Do not overlook teams that already maintain software inventories. Configuration Manager and Intune can help identify SQL Server installations on managed devices, while licensing and procurement records may identify systems purchased with SQL Server. Just remember the gaps: inventory tools cannot see unmanaged devices, and licensing records may not show free, bundled, or vendor-supplied editions such as SQL Server Express.

Once you've found an instance, confirm what it actually is. SQL Server 2016 builds have product versions that start with 13.0. Here's a quick example query.  

-- Sample query
SELECT
    SERVERPROPERTY('ServerName')     AS server_name,
    SERVERPROPERTY('ProductVersion') AS product_version,  -- 13.0.x = SQL Server 2016
    SERVERPROPERTY('ProductLevel')   AS product_level,    -- for example, SP3
    SERVERPROPERTY('Edition')        AS edition;

For each SQL Server 2016 instance you find, jot down at least the edition, patch level, host operating system, business owner, and the application it supports. If you can't name a business owner, that's the first thing to escalate. Until someone owns the server, nobody can make any of the decisions in the rest of this article.

Buying Time With Extended Security Updates

If your organization's main worry is critical security exposure, Microsoft does offer a way to buy time. Extended Security Updates (ESUs) provide security fixes for up to three more years, through July 17, 2029. Organizations that mostly care about staying covered against serious vulnerabilities are the ones most likely to stretch that runway as far as it goes, and to pay for the privilege.

Before anyone treats ESUs as a comfortable cushion, though, it's worth being clear about what you're actually getting. ESUs include only security updates rated Critical by the Microsoft Security Response Center, and only "if and when available", and as long as someone keeps paying. And don't confuse ESUs with support. ESUs don't give you the right to call Microsoft about a SQL Server 2016 problem; that takes a separate paid support plan. In my experience, Microsoft support has sometimes helped with older versions anyway, but not always, and it isn't obliged to. 

Honestly, most DBAs rarely open a support case these days. We search online, post in forums, and lately, ask AI. Just don't let that habit fool you into thinking critical issues are rare. In September 2026 alone, Microsoft fixed five Critical SQL Server vulnerabilities. 

There are also a few eligibility conditions. 

  • Only Enterprise and Standard editions qualify.
  • The instance has to be on the latest service pack, which for SQL Server 2016 means Service Pack 3. 
  • The instance also “has” to be connected to Azure Arc. However, this is not a strict technical requirement, or at least it is not strictly enforced. There are alternative ways to get ESU patches for disconnected servers, and technically nothing prevents someone from copying a patch from one server to another, except that it would be violation of the licensing terms. SQL Server ESUs do not require a separate license or product key.
  • You'll also need either active Software Assurance or pay-as-you-go billing through Arc. 

If you were counting on the SQL Server 2014 benefit where you can still get free ESUs through July 13, 2027 simply by moving SQL Servers to Azure VMs, it does not carry over to SQL Server 2016. Moving a SQL Server 2016 workload to an Azure VM no longer gives you free ESUs. 

The process is a little different for isolated or air-gapped servers. Volume Licensing customers do not have to connect those servers directly to Azure Arc, but they do need to manually register the SQL Server instances in the Azure portal to receive ESUs. That means disconnected environments still need a plan for registration, obtaining updates, and installing them, something I’ll come back to shortly.

And there may be a problem one layer down, too. If your SQL Server 2016 instance runs on Windows Server 2016, the operating system has its own deadline: January 12, 2027. Strictly speaking, that's not the DBA's problem. Even small shops that can't afford a full-time DBA usually have a sysadmin, or at least a jack of all trades, looking after Windows.  Microsoft sells ESUs for Windows Server 2016 as well, which means two subscriptions, two budget lines, and two sets of dates for the same server. Paying to keep the database patched while the operating system underneath it goes unpatched only protects half the box.

Time Moves Faster Than Budgets

Procrastination is human nature, and three years sounds like plenty of time. Microsoft splits it into three ESU years, ending July 13, 2027, July 18, 2028, and July 17, 2029. Each of those dates is a natural checkpoint, and sooner or later someone in leadership is going to look at the ESU line in the budget and ask, "Remind me why we're still paying for this?"

That's really the point. The hard decision doesn't arrive on July 17, 2029. It arrives much sooner, while there's still enough runway to actually act on it. And when it comes down to it, leadership has two real options. They can find a suitable alternative, whether that's a supported SQL Server version, a managed platform, a replacement application, or an upgraded release from the vendor. Or they can shut the server down: archive the data, retire the application, and accept whatever business capability goes with it.

"Keep paying and hope" isn't a third option, because the end date doesn't move. An organization that reaches mid-2028 without a funded plan doesn't get to choose anymore. It gets whatever can still be squeezed into the time that's left.

When It Has to Stay: Containing the Risk

Let's be realistic. Some databases are going to stay on unpatched SQL Server 2016 much longer than anyone would like. Maybe the vendor went out of business. Maybe the server can't meet the Azure Arc requirement. Maybe the budget just isn't there this year. The goal changes from fixing the risk to containing it. You assume new vulnerabilities will show up, and you work on limiting how far an attacker could get if one does.

None of what follows makes an unsupported server safe. Taken together, though, it makes the server harder to reach, harder to exploit, and a lot easier to keep an eye on.

Shrinking the Network Exposure

The single most effective thing you can do is make the server hard to reach in the first place. Put it in its own network segment or VLAN, and set firewall rules so that only the application servers that genuinely need it can talk to it on the SQL Server port. For administration, have DBAs connect through a hardened jump host rather than straight from their everyday workstations.

And if you don't need SQL Server Browser, turn it off so you're not advertising named instances to anyone who asks. Clients can still connect without it, as long as the instance listens on a fixed port and every connection includes that port, for example ProdSQL01\SQL202601,59555. Named instances use dynamic ports by default, so set a static port first, or the next restart could leave every connection string pointing at the wrong door. And "every connection" really means every one: applications, SQL Agent jobs, linked servers, SSIS packages, reports, and your own SSMS shortcuts. Leave Browser running on failover cluster nodes, and remember that a dedicated admin connection (DAC) to a named instance needs its port specified once Browser is off.

Reducing the Attack Surface Inside SQL Server

Next, look at what SQL Server itself can do. Features that let SQL Server reach out to the operating system deserve a hard look, especially xp_cmdshell, CLR integration, OLE Automation procedures, and ad hoc distributed queries. If nothing uses them, turn them off. Linked servers are worth a review as well, since each one is a path into or out of the instance. Remove the ones nobody uses, and be wary of login mappings that connect with highly privileged accounts. If components like Reporting Services, Integration Services, Analysis Services, or Full-Text Search are installed but unused, uninstall them.

Tightening Identity and Privilege

Then turn to who can do what. Clean up sysadmin membership, including old service accounts and people who left years ago. Run SQL Server services under low-privilege accounts, ideally managed or group managed service accounts, and never under a domain admin account. Lean on Windows authentication wherever you can, disable or rename sa, and make sure any remaining SQL logins have strong passwords. And give the application account only the permissions it actually needs. db_owner shouldn't be the default just because it was easiest at install time.

Protecting the Data Itself

Encrypt connections with TLS, and encrypt data at rest where your edition allows it. That second part has an edition wrinkle on SQL Server 2016: Transparent Data Encryption (TDE) is an Enterprise edition feature, while backup encryption is available in both Enterprise and Standard. Beyond encryption, keep immutable or offline copies of your backups. If the server is ever compromised, a clean backup the attacker couldn't reach is how you get back on your feet. And test your restores regularly. A backup you've never restored is more of a hope than a recovery plan.

Watching It More Closely

An unsupported server deserves more attention, not less. Turn on SQL Server Audit for logins, permission changes, and schema changes, and send those logs off the server to your organization's SIEM (What is SIEM?). SIEM is a platform, usually run by the security team, that collects logs from servers, network devices, and applications across the organization and analyzes them together to spot threats. 

On top of auditing, set up alerts for the things that should never happen quietly: new logins, sysadmin grants, bursts of failed logins, xp_cmdshell suddenly being re-enabled, or connections from hosts you don't recognize. And keep endpoint protection running on the host. If it causes performance trouble, work out exclusions with the security team rather than switching it off.

Putting the Risk on Paper

Finally, make the risk visible. Record a formal risk acceptance, signed by the business owner rather than the DBA team, that names the server, explains why it can't move, lists the compensating controls, and sets a review date. Then actually review it. A risk someone accepted in 2026 shouldn't just roll over automatically in 2028.

One last thought on this section. If a server is staying put specifically because it can't meet the Azure Arc requirement, it deserves the strictest isolation you can give it. It won't receive ESUs no matter who is willing to pay.

When the Vendor Holds the Keys

Some SQL Server 2016 instances are not fully under your control. They may be bundled with vendor-supplied systems, including access-control and badge systems, building-management platforms, medical or laboratory equipment, manufacturing and plant-floor software, phone systems, and appliances delivered as sealed physical servers or virtual machines.

In these environments, the vendor typically specifies which SQL Server versions, patches, configuration settings, and security tools are supported. Applying updates or making configuration changes outside the vendor’s guidance can affect supportability, application compatibility, or both.

That changes the DBA’s role. You may not be able to upgrade the instance, apply your standard hardening controls, or obtain sysadmin access without moving outside the vendor-supported configuration or affecting support coverage. At that point, the conversation is no longer purely technical, it also involves the vendor agreement, support terms, and organizational risk. The DBA team should be involved, but ownership usually sits with the system owner, vendor-management team, procurement, or legal.

Questions Worth Asking the Vendor

What you can do is make sure the right questions are asked and that the answers come back in writing. I’d start with these:

  • Which SQL Server versions does our current product release support? When will you support SQL Server 2022 or SQL Server 2025?
  • If we upgrade the database engine but retain database compatibility level 130, will you support the product in that configuration?
  • If a critical SQL Server 2016 vulnerability is disclosed, what is your response process, what mitigations can you provide, and how quickly can you deliver a supported fix?
  • Do you support Extended Security Updates for this system? If so, which ESU enrollment path do you support - Azure Arc, an Azure VM, or the disconnected Volume Licensing process, and who is responsible for registration, billing, patch acquisition, and installation?
  • Which hardening controls and security tools do you support, including endpoint protection, vulnerability scanning, auditing, and privileged-access controls?
  • If you do not plan to support a newer SQL Server version, what is the end-of-life date for this product release, and what is the supported migration path?

Insist on written answers. A verbal “we’re working on it” is not adequate evidence when an auditor or, worse, an incident review, asks why a server remained unpatched.

What You Can Still Control

Even when you can't touch the inside of the server, you usually have a lot of say over what surrounds it. Network segmentation, firewall rules, and blocking outbound internet access typically don't need vendor approval, because they don't change the vendor's software. Just check the vendor's documented network requirements first so you don't accidentally block something the system relies on, like license checks or connections to field devices. In practice, this is where most of your containment from the previous section will come from.

You can also control who gets in. Route administrative access through a jump host with named accounts, and that includes the vendor's own remote support connections. Turn their remote access on when they need it and off when they're done, and log it. Monitoring network traffic and collecting logs from the outside can often be added without touching anything the vendor certified. And make sure the data is backed up somewhere you control, even if the vendor's tool takes its own backups.

For anything that does touch the server itself, such as installing an agent, changing a security setting, or adding an endpoint protection exclusion, check with both the vendor and your security team first. An unapproved change can leave you in the worst of both worlds: a system the vendor won't support, running on a database Microsoft won't support.

Bringing In the People Who Own the Contract

Your strongest leverage over a vendor usually sits outside IT. Procurement, vendor management, and the business owner can tie renewals and support payments to a supported-platform roadmap. And if the vendor has no plan at all, take that as a signal about the product, not just the database. The real decision may be replacing the application, which takes far longer than any database upgrade. That's one more reason to start the conversation well before the final ESU year.

Upgrade the Engine, Keep the 2016 Behavior

For most organizations, the best and simplest path is to move the database to a supported version of SQL Server and leave its compatibility level at 130, the SQL Server 2016 level. SQL Server 2025 supports compatibility levels 100 through 170, so 130 is still on the menu. Better yet, starting with level 130, Microsoft deliberately ties new query plan-affecting fixes and features to newer compatibility levels only, which lowers the risk of your plans getting worse after the move. A database at level 100 or higher keeps its level when you move it to SQL Server 2025 (Supported version and edition upgrades). You end up on a supported, patched engine, and the application keeps seeing the behavior it's used to.

What Compatibility Level Won't Save You From

Here's the part that's easy to miss. Compatibility level controls Transact-SQL and query optimization behavior for that one database. It doesn't control the rest of the server. Anything outside that scope can still break, and a few things commonly do. The good news is that all of these are documented, so you can find them before they find you:

Breaking changes to Database Engine features in SQL Server 2025.

The trickier problems are the ones the application team built in themselves.

Removed features are the first thing to check. Data Quality Services and Master Data Services are discontinued in SQL Server 2025, on-premises Reporting Services is now consolidated under Power BI Report Server, Synapse Link is discontinued, and Web edition is gone. Setting compatibility level 130 won't bring any of them back.

Client drivers are another. SQL Server Native Client (SNAC) doesn't ship with SQL Server 2022 or later, so connection strings and linked servers that name SQLNCLI11 will need attention.

Encryption defaults have also tightened. After an upgrade to SQL Server 2025, linked servers that use Microsoft OLE DB Driver 19 can fail without a valid certificate, because the driver validates the server certificate by default. Replication publishers with a remote distributor, and remote log shipping monitors, can run into the same kind of trouble. 

And if you use Full-Text Search, SQL Server 2025 removes the legacy word breaker and filter binaries. Queries against existing version 1 full-text indexes fail until those indexes are rebuilt or recreated, although Microsoft does describe a temporary option to keep using version 1 components where supported.

Hard-Coded Assumptions

Some applications were written as if SQL Server 2016 would be around forever. The code might check @@VERSION or SERVERPROPERTY('ProductMajorVersion') and refuse to run unless the major version is 13. Agent jobs, backup scripts, or xp_cmdshell calls might reference paths like ...\MSSQL13.MSSQLSERVER\MSSQL\Backup. Old host names might be typed directly into connection strings, linked servers, SSIS packages, or report data sources. Connection strings might still say Provider=SQLNCLI11. And some code depends on a specific column order or on the exact output of a system procedure or DMV, which can change between versions.

A quick way to get a first look is to search the database's own code for these patterns. Here's an example query. I haven't tested it against your environment, so run it in each user database and treat what it returns as leads to follow up on rather than a complete list. It also won't see anything in application code, configuration files, SSIS packages, or Agent job steps.

-- Example only: find code that may assume SQL Server 2016
SELECT
    OBJECT_SCHEMA_NAME(m.object_id) AS schema_name,
    OBJECT_NAME(m.object_id)        AS object_name,
    o.type_desc
FROM sys.sql_modules AS m
JOIN sys.objects     AS o ON o.object_id = m.object_id
WHERE m.definition LIKE N'%@@VERSION%'
   OR m.definition LIKE N'%ProductMajorVersion%'
   OR m.definition LIKE N'%ProductVersion%'
   OR m.definition LIKE N'%MSSQL13%'
   OR m.definition LIKE N'%SQLNCLI%';

For Agent jobs, a similar search against msdb.dbo.sysjobsteps.command will cover the job steps.

Thinking Outside the Box

So what do you do when compatibility level can't save the application and nobody can fix the code? This is where a little creativity helps. None of the ideas below is a guaranteed fix, so test each one before you rely on it.

If the problem is a hard-coded server name, you may be able to redirect the name instead of changing the code. A DNS alias (CNAME), a SQL Server client alias, or an availability group listener that reuses the old server name can point those connection strings at the new instance. Each option has its catch, though. A client alias has to be configured on every application server. A listener can take the old name only after the old computer account has been retired or renamed. And Kerberos service principal names (SPNs) have to match whatever name clients connect with, or Windows authentication may fall back to NTLM or fail outright.

If jobs or scripts expect an MSSQL13 folder path, a directory junction or a matching folder structure on the new server can keep them happy while you schedule a proper fix. Just document it clearly, so the next DBA who stumbles across it isn't left scratching their head.

Version checks can sometimes be fixed more easily than you'd expect. If the check lives in a stored procedure inside the database, it might be a one-line change. If the application is vendor-supported, get the vendor's written approval first. There's no supported way to make SQL Server report an older version. You cannot use compatibility level to disguise a newer SQL Server as an older one. The database may retain older compatibility behavior, but the instance still reports its actual SQL Server version. So the check itself is what has to change. 

Old drivers are often easier to deal with on the client side. Installing a current ODBC or OLE DB driver on the application servers and updating the connection string is usually far less work than changing the application. Just plan for a trusted certificate on the server, since current drivers can enforce the same stricter encryption defaults mentioned earlier.

A managed platform is worth a look, too. Azure SQL Managed Instance also supports compatibility level 130, and as a fully managed service it doesn't reach end of support the way boxed versions do (SQL Server end of support options). It has its own feature differences, so think of it as a candidate to evaluate rather than an automatic fit.

Sometimes the answer is to separate the data from the application. If the application truly can't move but the data still matters, keep the application tightly isolated, copy the data to a supported reporting platform, and give users read-only access there. That way you can retire the old system on your own schedule instead of someone else's.

And sometimes the right answer is to retire it on purpose. Archive the database, export whatever records the business is legally required to keep, and shut the application down. Before assuming a system has to be saved, find out how many people actually still use it. You might be surprised. The system everyone was afraid to touch sometimes turns out to have only a handful of users left.

The Bottom Line

SQL Server 2016's end of support isn't an outage. It's a deadline for making a decision. Every remaining instance should land in one of three places: it's being moved, it's being protected while a funded plan is underway, or it's being retired. An instance that fits none of those is simply an unmanaged risk. So is the one nobody has found yet, and the one inside a vendor's system that nobody has asked the vendor about.

ESUs can buy you time until July 17, 2029, but only for critical fixes, only for Enterprise and Standard editions that can connect to Azure Arc, and only as long as someone keeps paying. Isolation and hardening can contain the risk, but they can't make it go away. And upgrading while keeping compatibility level 130 will handle most cases, as long as you check the things compatibility level was never designed to control.

In the end, the organizations that handle this well aren't necessarily the ones that upgrade first. They're the ones that know why each SQL Server 2016 instance is still running, who owns it, and when it's going away.

See Also