Fix it now
905 and 909 stop a database coming online because the edition you are starting it on cannot run something inside it. 905 names a partition function; 909 names an object using data compression or vardecimal. The database is intact. Ask the database what is in it before you buy anything, because the answer has changed since those messages were written.
SELECT feature_name FROM sys.dm_db_persisted_sku_features;
SELECT SERVERPROPERTY('Edition') AS TargetEdition, SERVERPROPERTY('ProductVersion') AS TargetVersion;
- Run the view on the source while the database is still open somewhere that can open it. Every row is a feature recorded inside the database.
- Check the target’s edition and version. From SQL Server 2016 Service Pack 1 onwards, Microsoft states those features except transparent data encryption became available across editions rather than Enterprise and Developer only.
- If the target is a current Standard instance, compare the rows against its own editions table before assuming Enterprise is required. Partitioning, data compression, columnstore and In-Memory OLTP are all supported on Standard today.
- If the target is Express, or an old build, remove the listed features on the source, take a fresh backup, and restore again.
The view needs a permission. Up to SQL Server 2019 that is VIEW DATABASE STATE on the database; from SQL Server 2022 it is VIEW DATABASE PERFORMANCE STATE. Without it you get an empty result, which reads exactly like “no blocking features” and is not.
If the database comes online on the target, you are done. If the view lists something the target genuinely cannot run, the next section covers what each entry means.
Why it happens
Some features leave a permanent mark inside the database rather than only in the instance that created it. Partitioned structures, certain compression and storage formats, change data capture, columnstore, In-Memory OLTP, transparent data encryption and multiple FILESTREAM containers are recorded in the database so that any engine opening it can see what it will be asked to do. sys.dm_db_persisted_sku_features lists exactly those marks, and when a target edition cannot run one, the check fails and the database is left offline before anything is read.
The two error numbers are more specific than they look. 905’s published text is that the database cannot be started in this edition because it contains a named partition function, and that only Enterprise edition supports partitioning. 909’s is that part or all of a named object is enabled with data compression or vardecimal storage format, and that those are only supported on Enterprise. 5069 is a companion, ALTER DATABASE statement failed, usually raised as the engine tried to bring the database online.
Both message texts are stale, and this is the single most important thing to know before spending money. Microsoft states that starting with SQL Server 2016 Service Pack 1, the features this view reports – all of them except transparent data encryption – became available across editions rather than being limited to Enterprise and Developer. The SQL Server 2025 editions tables bear that out: table and index partitioning, data compression, columnstore and In-Memory OLTP are all Yes for Standard, and transparent data encryption is Yes for Standard too.
So a database blocked by 905 or 909 today is almost always being restored to an old build, or to Express. Express is where the real edition boundary now sits: it has no transparent data encryption, no change data capture and no resource governor, and its memory-optimised and columnstore allowances are 352 MB rather than 32 GB.
The target is an old build, from before the features moved down
You have this one if The target is SQL Server 2016 RTM or earlier, or a 2016 instance that has never had Service Pack 1 applied, and the view lists compression or partitioning.
- Check the target’s build with
SELECT SERVERPROPERTY('ProductVersion'), SERVERPROPERTY('ProductLevel');before doing anything invasive. - Patch the target if it is a 2016 instance below Service Pack 1. That alone can remove the block without touching the database.
- If the target cannot be patched, remove the features on the source and restore again.
The target is Express
You have this one if The view lists TransparentDataEncryption, ChangeCapture, or an In-Memory OLTP or columnstore footprint larger than Express allows.
- Check the Express limits rather than guessing: no transparent data encryption, no change data capture, no resource governor, and 352 MB each for columnstore segment cache and memory-optimised data.
- Remove the feature on the source. Decrypt a TDE database, or disable change data capture, before taking the backup you intend to restore.
- Remember the relational database size ceiling as well, because a database large enough to have been partitioned is often too large for Express anyway.
The database uses compression the target cannot run
You have this one if 909 names an object, and the view shows a Compression entry.
- List what is compressed:
SELECT OBJECT_NAME(p.object_id) AS ObjectName, p.index_id, p.data_compression_desc FROM sys.partitions AS p WHERE p.data_compression <> 0; - Rebuild each one without compression:
ALTER TABLE dbo.YourTable REBUILD WITH (DATA_COMPRESSION = NONE);and repeat for every non-clustered index involved. - Confirm the view no longer returns a Compression row, take a fresh backup, and restore to the target.
Removing compression makes the database substantially larger, sometimes several times over. Check free space on both sides first, and expect the rebuilds to be fully logged and slow. This is maintenance window work.
The database uses partitioning
You have this one if 905 names the database and the view shows a Partitioning entry.
- Find the partitioned objects through
sys.partition_schemes,sys.partition_functionsandsys.indexes. - Rebuild each partitioned clustered index onto a single filegroup instead of a partition scheme, then the non-clustered indexes the same way.
- Drop the partition schemes and functions once nothing references them, back up and restore.
This is a redesign, not a setting. If partitioning was there for rolling windows or partition switching during loads, removing it costs you those operations and the load process has to be rewritten.
You are consolidating downwards and found out at cutover
You have this one if The plan was to move from Enterprise onto a lower edition, and the databases will not come online after restore.
- Run the view against every database you intend to move, while they are still on the higher edition. Do this before the migration, not after it fails.
- Remove or replace each listed feature there, and retest the workload without it.
- Only then move the databases. If a feature cannot be removed without losing something the business depends on, the downgrade is not free and should be costed as such.
There is no in-place edition downgrade. Moving down means a separate installation of the lower edition and a restore, which is exactly the moment this error appears.
Full reference
What the view can return, and what each entry means
| feature_name | What it records |
|---|---|
ChangeCapture |
Change data capture is enabled on the database |
ColumnStoreIndex |
At least one table has a columnstore index |
Compression |
At least one table or index uses data compression or the vardecimal storage format |
MultipleFSContainers |
The database uses multiple FILESTREAM containers |
InMemoryOLTP |
The database uses In-Memory OLTP |
Partitioning |
The database contains partitioned tables or indexes, partition schemes or partition functions |
TransparentDataEncryption |
The database is encrypted with transparent data encryption |
Which of those still constrains you
| Feature | Enterprise | Standard (2025) | Express (2025) |
|---|---|---|---|
| Table and index partitioning | Yes | Yes | Yes |
| Data compression | Yes | Yes | Yes |
| Columnstore | Yes | Yes | Yes, within a 352 MB segment cache |
| In-Memory OLTP | Yes | Yes, within 32 GB per database | Yes, within 352 MB per database |
| Transparent data encryption | Yes | Yes | No |
| Change data capture | Yes | Yes | No |
| Resource governor | Yes | Yes | No |
Read that table before reading the error message, because the error message pre-dates it. The realistic modern block is a restore onto Express, or onto a build old enough that the 2016 Service Pack 1 change had not happened.
Reading the block
| What you see | What it means |
|---|---|
| The restore finishes but the database stays offline | The feature check blocked bringing it online |
| 909 naming an object | Data compression or vardecimal storage format on that object |
| 905 naming a partition function | Partitioning |
| 5069 in the same sequence | An ALTER DATABASE statement failed, typically while the engine tried to bring the database online |
| The view returns no rows on the source | Either there is genuinely nothing persisted, or you lack the permission the view requires |
| It works on one instance and not another on the same machine | Those two instances are different editions or different builds |
Removing compression, carefully
SELECT OBJECT_NAME(p.object_id) AS ObjectName,
p.index_id,
p.data_compression_desc
FROM sys.partitions AS p
WHERE p.data_compression <> 0
ORDER BY ObjectName, p.index_id;
ALTER TABLE dbo.YourTable REBUILD WITH (DATA_COMPRESSION = NONE);
ALTER INDEX IX_YourIndex ON dbo.YourTable REBUILD WITH (DATA_COMPRESSION = NONE);
Permissions on the view
- Up to SQL Server 2019,
sys.dm_db_persisted_sku_featuresrequires VIEW DATABASE STATE on the database. - From SQL Server 2022 it requires VIEW DATABASE PERFORMANCE STATE.
- Without the permission the view returns nothing rather than raising an error, so an empty result is not proof of anything.
- Run it as a member of sysadmin, or grant the permission explicitly, before you conclude a database is portable.
Establishing what the target can actually run
| Question | How to answer it |
|---|---|
| What edition is the target? | SELECT SERVERPROPERTY('Edition'), SERVERPROPERTY('EditionID'); |
| What build is the target? | SELECT SERVERPROPERTY('ProductVersion'), SERVERPROPERTY('ProductLevel'); |
| What does the source database persist? | SELECT feature_name FROM sys.dm_db_persisted_sku_features; run on the source |
| Does the target edition support each of those? | The editions and supported features page for the target release |
| Is the target below SQL Server 2016 SP1? | Then the old Enterprise-only rules still apply and patching the target may be the whole fix |
Those five answers, taken together, decide whether this is a five-minute patch, a rebuild of some indexes, or a purchase. Taking them in that order also stops the most expensive mistake, which is reading the error message text, seeing the word Enterprise, and buying on that basis alone.
Planning a move so this never happens at cutover
Run the view against every database while it is still on the source, and record the output alongside the target edition and build. That converts a failed cutover into a planning exercise, and it takes seconds per database. Where a row appears, check it against the target’s own editions table rather than against the error message text, because the message text names Enterprise for things Standard has run for several releases now.
When a licence is the actual fix
Check the view before you spend anything, because the honest answer is usually that you do not need to. Microsoft states that from SQL Server 2016 Service Pack 1 the features this view reports, except transparent data encryption, became available across editions, and the SQL Server 2025 editions tables list partitioning, data compression, columnstore, In-Memory OLTP and transparent data encryption as supported on Standard. So a database blocked today is normally being restored onto Express or onto an old build, and the fix is a newer or higher target rather than Enterprise specifically. Where Enterprise is genuinely the answer it is because of scale rather than these features – beyond Standard’s documented 256 GB buffer pool and 32-core compute ceiling on SQL Server 2025, or beyond its 32 GB columnstore and memory-optimised allowances. SQL Server 2025 Enterprise (2-core pack) removes those, and moving a target up is an in-place edition upgrade rather than a migration. Send Arco the view’s output and your core count and we will tell you which edition it actually implies.
Every code this article covers
| Code | What it points at | Source |
|---|---|---|
905 |
The database cannot be started in this edition because it contains a named partition function; the message adds that only Enterprise supports partitioning, which has not been true since SQL Server 2016 SP1 | Microsoft Learn |
909 |
The database cannot be started in this edition because part or all of a named object uses data compression or vardecimal storage format; the same caveat applies to its Enterprise-only wording | Microsoft Learn |
5069 |
ALTER DATABASE statement failed, usually raised alongside the feature check while the engine tried to bring the database online | Microsoft Learn |
Confirm the fix worked
- The database comes online and
state_descinsys.databasesreads ONLINE. SELECT feature_name FROM sys.dm_db_persisted_sku_features;on the restored copy returns nothing the target edition cannot serve.- You ran that view as an account holding the permission it requires, so an empty result means something.
- Application queries return against the tables you rebuilt, and row counts match the source.
DBCC CHECKDBcompletes cleanly on the restored database.
Questions people ask about this
Is my database damaged?
No. It is complete and consistent, and it opens normally on any instance whose edition and build support what it uses. Nothing was written during the failed attempt, so you can attach it back to the original server and carry on while you plan.
The error says only Enterprise supports partitioning. Is that right?
Not any more. That wording dates from before SQL Server 2016 Service Pack 1, and Microsoft’s current editions tables list table and index partitioning as supported on Standard and Express. Check the target’s editions table rather than the message text.
Can I force it online anyway?
There is no supported override, and that is deliberate. The check exists to stop an engine trying to run structures it does not implement, which would fail later and less predictably than it does now.
Why did the view return nothing when the restore clearly failed?
Most likely a permission. The view needs VIEW DATABASE STATE up to SQL Server 2019 and VIEW DATABASE PERFORMANCE STATE from SQL Server 2022, and without it you get an empty result rather than an error.
What actually still forces Enterprise?
Scale, mainly: beyond Standard’s documented buffer pool, compute, columnstore and memory-optimised ceilings. The features this view reports are not the boundary they were, so run the view and compare it against the target’s editions table before treating Enterprise as the only option.
