RE:NODE

Databases11 min read

SQL Server Express hosting: limits and when it is enough

What SQL Server 2022 Express can and cannot do: the 10 GB per database cap, memory and CPU limits, missing features like Agent, and when to move up.

0 readers

SQL Server Express is the free edition of Microsoft SQL Server, licensed for production, and it is the same database engine as the paid editions with a few hard ceilings. In SQL Server 2022 those ceilings are: 10 GB of data per database, about 1.4 GB of memory for the buffer pool, the lesser of one socket or four cores, and no SQL Server Agent. For a typical web application, an internal tool, a game backend or a small SaaS, that is enough - often for years. It stops being enough when one database approaches 10 GB, when the working set no longer fits in 1.4 GB of cache, or when you need scheduled jobs, replication or high availability inside the engine. This post goes through each limit, what happens when you hit it, how to watch for it, and the honest point at which to move to something else.

What SQL Server Express is#

Microsoft ships SQL Server in editions that share one codebase: Enterprise, Standard, Web (for hosting providers), Developer (Enterprise features, licensed for development and testing only) and Express. Express is the free production edition. It runs the same query optimiser, the same storage engine and the same T-SQL as the others, and a database created on Express can be backed up and restored onto Standard or Enterprise of the same or a newer version without conversion.

Since SQL Server 2016 SP1, a long list of features that used to be Enterprise-only work in every edition, Express included. That changed what "Express" means: it is no longer a cut-down engine, it is the full engine with capacity limits.

Available in Express:

  • Columnstore indexes, in-memory OLTP (memory-optimised tables), table partitioning and data compression, within Express's memory caps.
  • Row-level security, dynamic data masking and Always Encrypted.
  • Temporal tables, JSON functions, window functions, STRING_AGG, and the rest of modern T-SQL.
  • Query Store, for tracking query plans and performance over time. Query Store and slow queries covers how to use it.
  • Full recovery model and transaction log backups, so point-in-time restore is possible.

Not available in Express:

  • SQL Server Agent, the built-in job scheduler. No scheduled jobs, no maintenance plans, no alerts.
  • Backup compression. Backups work; they are not compressed by the engine.
  • Database Mail, log shipping, Always On availability groups and failover clusters.
  • Replication as a publisher. Express can only be a subscriber.
  • Resource Governor and the other Enterprise-only workload controls.

SQL Server 2022 also runs on Linux, which is how most hosted Express servers run today. The engine is the same; what differs is mostly around the edges - paths, configuration through mssql-conf instead of SQL Server Configuration Manager, and a few Windows-only features. SQL Server on Linux explained goes through those differences.

The limits in detail#

LimitSQL Server 2022 ExpressWhat it means in practice
Database size10 GB per databaseData files only; the transaction log is not counted
Buffer pool memory1,410 MB per instanceThe cache for data pages; the process uses more in total
Columnstore cache352 MB per instanceOnly matters if you use columnstore indexes
Memory-optimised data352 MB per databaseOnly matters if you use in-memory OLTP
ComputeLesser of 1 socket or 4 coresExtra cores beyond four sit unused
Databases per instance32,767 (same as other editions)The cap is per database, not per server

The 10 GB limit applies to each database separately and counts only the data files (.mdf and any .ndf), not the log file (.ldf). Two consequences are worth stating plainly. First, an instance can hold several databases of up to 10 GB each - separate applications should have separate databases anyway, and that also keeps each one under the cap. Second, a large transaction log does not eat into the 10 GB; it eats into your disk instead, which is its own problem covered below.

The memory limit is a cap on the buffer pool - the cache of data pages that makes repeated reads fast - not on the whole process. SQL Server also uses memory for query plans, connections, sorts and its own code, so a busy Express instance commonly uses more than 1.4 GB in total. What the cap means is that a database whose frequently read data is larger than about 1.4 GB will be read from disk more often than it would on Standard. On fast NVMe storage that costs less than it used to, but it is still the limit you feel first on a read-heavy app.

The compute limit is four cores. A server with more cores than that does not make Express faster; a server with fewer gives Express less to work with.

How to tell how close you are#

Check database size from any query window:

sql
-- Size of data and log files in the current databaseSELECT name, type_desc,       size * 8 / 1024 AS size_mb,       FILEPROPERTY(name, 'SpaceUsed') * 8 / 1024 AS used_mbFROM sys.database_files;-- Overall, including unallocated spaceEXEC sp_spaceused;

size is the allocated file size and SpaceUsed is how much of it holds data. The 10 GB limit is enforced on the allocated size of the data files, so a data file that has grown to 9.5 GB and is half empty is closer to the ceiling than its contents suggest.

To see which tables are using the space:

sql
SELECT TOP (20)       s.name + '.' + t.name AS table_name,       SUM(p.reserved_page_count) * 8 / 1024 AS reserved_mb,       SUM(CASE WHEN p.index_id IN (0, 1) THEN p.row_count END) AS row_countFROM sys.dm_db_partition_stats AS pJOIN sys.tables AS t ON t.object_id = p.object_idJOIN sys.schemas AS s ON s.schema_id = t.schema_idGROUP BY s.name, t.nameORDER BY reserved_mb DESC;

Run that monthly, or put it in a monitoring script. The tables at the top are nearly always logs, audit trails, sessions or blobs that nobody planned to keep forever.

To see how the buffer pool is being used:

sql
SELECT DB_NAME(database_id) AS db,       COUNT(*) * 8 / 1024 AS cached_mbFROM sys.dm_os_buffer_descriptorsGROUP BY database_idORDER BY cached_mb DESC;

If the cached total sits at the cap and query latency climbs with traffic, memory is the constraint. If the cached total is well below the cap, memory is not your problem and a bigger edition would not help.

What happens at 10 GB#

Nothing gradual. When a data file needs to grow and growing would take the database past 10 GB, the growth is refused. Inserts and updates that need new pages fail with an error like:

code
Could not allocate space for object 'dbo.AuditLog'.'PK_AuditLog' in database 'app'because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files,dropping objects in the filegroup, adding additional files to the filegroup, or settingautogrowth on for existing files in the filegroup.

Reads keep working, which is why some applications appear half-alive: pages load, nothing saves. An ALTER DATABASE that tries to grow a file past the limit is refused with a message about exceeding the licensed limit of 10240 MB per database.

Getting back under the limit:

  1. Delete what you do not need. Old log rows, expired sessions, soft-deleted records. Delete in batches (DELETE TOP (5000) ... WHERE CreatedAt < ... in a loop) so each transaction stays small.
  2. Move blobs out. Files stored in varbinary(max) columns are the fastest way to fill 10 GB. Put them in object storage and keep a key in the table.
  3. Compress. Page compression (ALTER TABLE dbo.AuditLog REBUILD WITH (DATA_COMPRESSION = PAGE)) is available in Express and often shrinks large, repetitive tables by half or more, at some CPU cost on writes.
  4. Split by purpose. Archive or reporting data can live in a second database on the same instance, with its own 10 GB.

Shrinking the file afterwards (DBCC SHRINKFILE) gives the allocated space back but fragments indexes badly; do it once after a large cleanup, then rebuild the indexes that matter, and never put shrink on a schedule.

No SQL Server Agent: scheduling without it#

Agent is what most SQL Server tutorials use for nightly backups, index maintenance and statistics updates. On Express it is not there, so those jobs move outside the engine. Three workable options:

  • The host's scheduler. On RE:NODE, SQL Server plans carry 1 to 4 backup slots, and the Schedules tab runs ordered tasks from a cron expression - including a backup - so the nightly copy is configuration, not a script you keep alive. Backups are stored off the machine they protect, can be locked against rotation, downloaded, and restored with a button.
  • `sqlcmd` from another machine on a timer. A cron job or Windows Task Scheduler entry on a machine you control runs sqlcmd with a script file - BACKUP DATABASE, index maintenance, anything T-SQL can do. sqlcmd and bcp covers the command line, and SQL Server backup and restore covers the backup commands themselves.
  • The application's own job runner. A .NET worker service or Hangfire job can run maintenance T-SQL on a schedule. Fine for statistics and cleanup; less ideal for backups, because a backup should not depend on the app being healthy.
sql
-- A minimal nightly maintenance script for sqlcmdBACKUP DATABASE [app] TO DISK = N'/var/opt/mssql/backup/app.bak'    WITH INIT, CHECKSUM, STATS = 10;EXEC sp_updatestats;

The backup path above is the default backup directory on Linux installs; a hosted server may use a different one, so check before relying on it. A .bak file that stays on the same disk as the database is not a backup in any useful sense - copy it off.

The other thing Agent normally does is index and statistics maintenance. Statistics are updated automatically when enough rows change (AUTO_UPDATE_STATISTICS is on by default), which covers most small databases. Index rebuilds matter less on SSD and NVMe storage than older advice suggests; rebuild an index when you can show fragmentation is hurting a specific query, not on a timer.

Sizing a server for Express#

Because Express caps memory and cores, there is a point past which a bigger server buys nothing for the engine itself.

WorkloadMemoryvCPUComment
One small app database, light traffic2 GB1Buffer pool under the cap with room for the OS
A busy app or several small databases3-4 GB2-3Lets the buffer pool reach its 1.4 GB cap comfortably
Several databases near 10 GB each4-6 GB3-4Disk and CPU matter more than extra memory

Beyond roughly 4 GB of total memory, extra RAM mostly sits unused by the engine. Beyond four cores, Express cannot use them. What does keep scaling is disk: each additional database can be up to 10 GB, and logs, backups and tempdb all need room. On RE:NODE the SQL Server line runs from Express Starter (2 GB, 10 GB disk, 1 vCPU) to Express Max (6 GB, 80 GB disk, 4 vCPU), starting at $6 a month; the larger tiers are about room for more databases and the full four cores rather than more cache.

Watch the transaction log as well as the data. In the full recovery model the log grows until a log backup truncates it, and with no Agent to take log backups, a database in full recovery that nobody backs up grows its log until the disk is full. Check which model your databases use:

sql
SELECT name, recovery_model_desc FROM sys.databases;

If you are not taking log backups, use SIMPLE. Recovery models and log growth explains the trade.

When Express is not enough#

Move off Express when one of these is true, not before:

  • A single database is heading past 10 GB and cleanup, compression and splitting are not realistic. Standard edition raises the size limit to the operating system's.
  • The working set is far larger than 1.4 GB and you can show disk reads are the bottleneck. Standard allows a buffer pool of up to 128 GB.
  • You need high availability inside SQL Server - availability groups, failover clustering, log shipping. None of these exist in Express.
  • You need Agent-driven jobs, Database Mail alerts or replication as a publisher and an external scheduler is not acceptable.

The usual destinations are Standard edition on a server you license yourself (per core or server plus CALs, a significant cost), Azure SQL Database or Azure SQL Managed Instance, or a different engine. For a new project with no SQL Server dependency, PostgreSQL has no edition limits at all; which database should I use compares them by job. Moving an existing database up an edition is a backup and restore: the .bak from Express restores onto Standard or Enterprise of the same or newer version unchanged. Migrating a database to SQL Server hosting covers the other direction and the version rules.

What you should not do is run Developer edition in production to dodge the limits. It is free and has every feature, and its licence forbids production use.

FAQ#

Is SQL Server Express free for commercial use?

Yes. Express is licensed for production and commercial use at no cost. What you pay a host for is the server it runs on, not a SQL Server licence.

Does the 10 GB limit include the transaction log?

No. Only data files count. The log can grow beyond 10 GB, limited by disk space, which is why an unmanaged log in the full recovery model is a real risk on small servers.

Can I have more than one 10 GB database on one Express instance?

Yes. The limit is per database. Splitting unrelated data into separate databases is normal practice and keeps each under the cap.

Will giving Express more RAM make it faster?

Up to a point. The buffer pool stops at 1,410 MB, so memory beyond what that cap, the operating system and the rest of the engine need is unused. If the cache is already at its cap and disk reads are the bottleneck, the next step is better indexes or a different edition, not more RAM.

Can I restore an Express backup onto Standard or Azure SQL?

Onto Standard or Enterprise of the same or a newer version, yes, directly. Azure SQL Database does not restore .bak files; you move to it with a .bacpac export or a migration tool. Azure SQL Managed Instance does restore native backups.

Does SQL Server Express support stored procedures and triggers?

Yes. All of T-SQL is available, including stored procedures, functions, triggers, views, CTEs and window functions. The limits are capacity and a handful of server features, not the language.


Comments

Completely anonymous: no account, no email, no cookie. We store the name you type, the text and the time - nothing else. Links are limited and markup is not rendered.

0/2000