Key takeaways
- All content, Document Types, users, members, versions and Forms data live in one SQL Server or SQLite database, reached through the umbracoDbDSN connection string.
- Property values are stored per content version in umbracoPropertyData, with separate columns for integer, decimal, date, short text and long text values.
- Since Umbraco 15 the published cache is HybridCache: lazy loaded into memory, optionally backed by a distributed cache, and rebuilt from the cmsContentNu table.
- Media files are not in the database; they live in wwwroot/media by default or in Azure Blob Storage through the official storage provider.
- Examine indexes, logs and temp files are disposable or rebuildable, so a complete backup is the database plus the media store plus your code and config.
Umbraco stores its data in three places. Content, Document Types, Data Types, users, members, permissions, content versions and Umbraco Forms data all live in a relational database, either Microsoft SQL Server (including Azure SQL) or SQLite. Media files such as images and PDFs live outside the database, in the wwwroot/media folder by default or in cloud blob storage. Everything else on disk, including Examine search indexes, Serilog log files and temp files, sits in the umbraco folder of the running application and can be rebuilt.
So when someone asks where Umbraco stores data, the practical answer is: the database is the source of truth, the media store holds the files, and the rest is cache. The sections below map each piece to a table, folder or setting, using current Umbraco 17 LTS and 18 behavior, and explain what that means for backups, load balancing and cloud hosting.
Where Umbraco stores data at a glance
| Data | Where it lives by default | Can it be rebuilt? |
|---|---|---|
| Content, versions, property values | Database (umbracoNode, umbracoContent*, umbracoPropertyData, …) |
No, back it up |
| Document Types, Data Types, templates metadata | Database (cmsContentType, cmsPropertyType, umbracoDataType, cmsTemplate) |
No, but can be serialized to files |
| Users, user groups, members | Database (umbracoUser*, cmsMember*) |
No |
| Forms definitions and submissions | Database (Umbraco Forms tables) | No |
| Published content cache | Memory, optional distributed cache, plus cmsContentNu in the database |
Yes |
| Media files | wwwroot/media or Azure Blob Storage |
No, back it up |
| Examine (Lucene) indexes | umbraco/Data/TEMP/ExamineIndexes |
Yes |
| Logs | umbraco/Logs (JSON files from Serilog) |
Not needed for restore |
| Configuration | appsettings.json, environment variables, secret stores |
Lives in source control and secrets |
| Razor views, code, packages | Project files and /Views |
Lives in source control |
| Deploy or uSync schema files | umbraco/Deploy/Revision or the uSync folder |
Lives in source control |
The Umbraco database: SQL Server or SQLite
Umbraco’s requirements page lists two database options: SQL Server, with SQL Server 2016 as the minimum, and SQLite. SQL Server must use a case-insensitive collation such as SQL_Latin1_General_CP1_CI_AS, because Umbraco’s data access layer does not support case-sensitive naming. Azure SQL Database and Amazon RDS for SQL Server are both SQL Server from Umbraco’s point of view, and Umbraco Cloud runs each environment on its own Azure SQL database.
The connection string is always named umbracoDbDSN and sits in the root ConnectionStrings section, not under Umbraco:CMS:
{
"ConnectionStrings": {
"umbracoDbDSN": "Server=sql.example.internal;Database=Umbraco;User Id=umbraco;Password=<from secret store>;TrustServerCertificate=true",
"umbracoDbDSN_ProviderName": "Microsoft.Data.SqlClient"
}
}
Illustrative SQL Server connection string; keep the real password in a secret store or environment variable, not in source control.
With SQLite, the connection strings documentation shows Data Source=|DataDirectory|/Umbraco.sqlite.db, which puts the database file in /umbraco/Data. Umbraco creates SQLite databases in write-ahead logging mode and warns against adding Cache=Shared to the connection string.
SQLite vs SQL Server in production
SQLite is fully supported by the CMS and is the fastest way to start a project locally. It is a single file on the local disk of one server, though, so it does not fit load-balanced setups, containers with ephemeral storage or teams that need point-in-time restore. Some third-party packages also assume SQL Server. Our rule of thumb: SQLite for local development, demos and small single-server sites; SQL Server or Azure SQL for anything business critical.
Key Umbraco database tables
Umbraco’s table names are defined in Constants-DatabaseSchema.cs in the CMS source. The prefixes are historical: older tables start with cms, newer ones with umbraco. These are the ones you meet most often when debugging or reporting.
The tree: umbracoNode
umbracoNode holds one row for every tree item: documents, media, members, Document Types, Data Types, templates and more. The nodeObjectType column (a GUID) tells you which kind of entity the row is. Other important columns are id, uniqueID (the GUID key), parentId, level, path (a comma-separated list of ancestor IDs such as -1,1061,1078), sortOrder, trashed and text (the node name). The path column is why Umbraco can answer “all descendants of X” with a single LIKE query.
Content and versions
| Table | What it stores |
|---|---|
umbracoContent |
One row per content, media or member item, linking the node to its content type |
umbracoContentVersion |
Every saved version: nodeId, versionDate, userId, current, text, preventCleanup |
umbracoDocument |
Document-level state such as published and edited flags |
umbracoDocumentVersion |
Per version: published flag and templateId |
umbracoContentVersionCultureVariation / umbracoDocumentCultureVariation |
Names and publish state per language for variant content |
umbracoContentSchedule |
Scheduled publish and unpublish dates |
umbracoMediaVersion |
Media-specific version data such as the file path |
umbracoDocumentUrl |
Pre-computed URL segments used for routing |
umbracoRedirectUrl |
Automatic redirects created when a page moves or is renamed |
Umbraco 18 adds umbracoElement, umbracoElementVersion and umbracoElementCultureVariation for the new Elements library, which stores reusable content outside the document tree.
Schema: content types, properties and Data Types
cmsContentType describes Document Types, Media Types and Member Types. cmsPropertyTypeGroup holds tabs and groups, and cmsPropertyType holds each property: its alias, name, which Data Type it uses, and whether it varies by culture or segment. umbracoDataType stores Data Type configuration, for example which blocks a Block Grid allows. cmsContentType2ContentType records compositions, and cmsContentTypeAllowedContentType records which child types are allowed.
Property values: umbracoPropertyData
This is the table most people are looking for. Every property value is a row in umbracoPropertyData, keyed by versionId, propertyTypeId, languageId and segment. The value goes into one of several typed columns depending on the property editor’s storage type: intValue, decimalValue, dateValue, varcharValue or textValue.
Three consequences matter for architects:
- Values are stored per version. Saving a page with 40 properties writes up to 40 new rows. A busy site with long version history grows this table quickly.
- Complex editors store JSON. Block Grid, Block List, Multi URL Picker and similar editors serialize their value as JSON into
textValue. A whole page built in Block Grid can be one large JSON value, so you cannot query an individual block with plain SQL. - Variants multiply rows. A property that varies by culture has one row per language per version.
To keep the version tables under control, Umbraco runs an hourly cleanup job driven by Umbraco:CMS:Content:ContentVersionCleanupPolicy. The content settings documentation shows defaults of KeepAllVersionsNewerThanDays: 7 and KeepLatestVersionPerDayForDays: 90. EnableCleanup defaults to false when it is not set in configuration, but the dotnet new umbraco template sets it to true, so check what your project actually has. Versions marked “prevent cleanup” are kept, and Document Types can override the policy in umbracoContentVersionCleanupPolicy.
{
"Umbraco": {
"CMS": {
"Content": {
"ContentVersionCleanupPolicy": {
"EnableCleanup": true,
"KeepAllVersionsNewerThanDays": 7,
"KeepLatestVersionPerDayForDays": 90
}
}
}
}
}
Users, members, relations and system tables
- Back-office users:
umbracoUser,umbracoUserGroup,umbracoUser2UserGroup,umbracoUserStartNode,umbracoUserGroup2Permission,umbracoUserGroup2GranularPermission, plusumbracoExternalLoginandumbracoTwoFactorLogin. - Members:
cmsMember,cmsMemberTypeandcmsMember2MemberGroup. Member properties use the sameumbracoPropertyDatatable as content. - Relations and tags:
umbracoRelation,umbracoRelationType,cmsTags,cmsTagRelationship. Umbraco tracks media and document references here, which is how it warns you before deleting a referenced item. - Languages and dictionary:
umbracoLanguage,cmsDictionary,cmsLanguageText, andumbracoDomainfor Culture and Hostnames. - Audit and logs:
umbracoAuditandumbracoLogkeep an audit trail of user actions. These are not the Serilog application logs. - Load balancing:
umbracoServerregisters instances andumbracoCacheInstructionqueues cache refresh instructions for other servers. - Housekeeping:
umbracoKeyValuestores migration state for Umbraco and packages,umbracoLockhandles distributed locks, and theumbracoWebhook*tables hold webhook configuration and logs.
Umbraco Forms keeps form definitions, workflows, prevalues and submissions in the database too. The Forms documentation states that on current versions it is only possible to store Forms data in the database.
A warning on direct SQL. Reading these tables for reports or diagnostics is fine. Writing to them is not: it bypasses caches, indexes, relations and notifications. Use the ContentService, MediaService and other Umbraco services, or the Management API, for changes.
The published cache: NuCache, HybridCache and cmsContentNu
Front-end requests do not query umbracoPropertyData directly. Umbraco serves published content from a cache.
Umbraco 8 to 14 used NuCache. It loaded the whole published tree into memory at startup and kept local cache files on disk, which made startup slow on large sites and caused file locking issues in some hosting setups.
Umbraco 15 and later use HybridCache, built on Microsoft’s HybridCache library. The Umbraco 15 release post describes the move from an eager cache, where all content is cached all the time, to a lazy-loaded one. Only seeded content is loaded at startup; everything else is loaded the first time it is requested and then kept in memory.
Where the data lives in the HybridCache model:
- In-process memory (called L0 in Umbraco’s docs): converted content objects. By default this cache is unbounded. From Umbraco 18.1 you can cap it with
MaximumLocalCacheItemsand the opt-inUmbraco.Cms.PublishedCache.HybridCache.Boundedpackage. - Optional distributed cache (L2): if you register a distributed cache such as Redis, entries are shared across servers.
RemoteCacheDurationdefaults to one year. - Database cache: serialized published and draft data for each item is stored in the
cmsContentNutable. When a content type changes structurally, Umbraco rebuilds the affectedcmsContentNurows, and from 17.4 you can defer that rebuild withContentTypeRebuildMode: "Deferred".
Seeding is controlled under Umbraco:CMS:Cache. ContentTypeKeys lists Document Types to always preload, and DocumentBreadthFirstSeedCount and MediaBreadthFirstSeedCount (default 100) preload the top of the tree. The cache seeding docs note that the first request for unseeded content waits for a database round trip, so latency between the web server and the database matters more than it did with NuCache.
On the Auto.co.il rebuild, a car portal on Umbraco 15 with about 100,000 nodes imported from a legacy CRM, catalog and article search run on Lucene, and the team layered custom caching over Umbraco’s hybrid cache for the catalog pages. That pattern, platform cache for content plus an application cache for expensive computed views, is common on large Umbraco sites.
Media files: local disk vs blob storage
The database holds the media item, its properties (width, height, size, extension) and the file path. The bytes themselves are handled by Umbraco’s media file system. According to the FileSystemProviders documentation, the default is PhysicalFileSystem writing to /media inside wwwroot.
Your options:
- Default local folder. Simple, but each web server has its own disk, so it breaks as soon as you scale out unless you add file replication or a shared drive.
- Physical path outside the webroot. Set
Umbraco:CMS:Global:UmbracoMediaPhysicalRootPathto a local or network path. Umbraco wires it into the web root file provider so image resizing still works. - Azure Blob Storage. Install
Umbraco.StorageProviders.AzureBlob, add.AddAzureBlobMediaFileSystem()to the Umbraco builder inProgram.cs, and configureUmbraco:Storage:AzureBlob:Media:ConnectionStringandContainerName. The companionUmbraco.StorageProviders.AzureBlob.ImageSharppackage stores resized image cache in blob storage too, by default in a/cachefolder in the media container. See the Umbraco.StorageProviders repository. - Amazon S3 or other stores. There is no official Umbraco S3 provider in that repository; you use a community package or implement
IFileSystemyourself.
// Program.cs (illustrative)
builder.CreateUmbracoBuilder()
.AddBackOffice()
.AddWebsite()
.AddComposers()
.AddAzureBlobMediaFileSystem()
.AddAzureBlobImageSharpCache()
.Build();
One detail catches teams during migrations: the docs note that a file’s URL is stored on the media item when it is saved, so changing the provider does not move existing files. You copy the files and, if the path changed, update the stored paths.
On Alliant’s multi-site platform, media lives in Azure Blob Storage, traffic runs through Azure Load Balancer and releases go out through Azure CI/CD pipelines. Keeping media off the web servers is what lets several instances serve the same files. Umbraco Cloud makes the same choice: its documentation says all media on Cloud projects is stored in Azure Blob Storage.
Over time media libraries collect files nothing references any more. Our free MediaRemove package, available for Umbraco 10 to 13, scans content for media references and lists unused files so you can clean them up before a migration.
Examine and Lucene indexes on disk
Umbraco’s built-in search, Examine, is a wrapper around Lucene.NET. The Examine settings define three LuceneDirectoryFactory options:
Default: indexes inumbraco/Data/TEMP/ExamineIndexes.SyncedTempFileSystemDirectoryFactory: works on a copy in the process temp folder and syncs back toumbraco/Data/TEMP/ExamineIndexes.TempFileSystemDirectoryFactory: indexes only in the process temp folder.
Indexes are derived data. Every server keeps its own copy, and they can be rebuilt from the database from the Examine Management dashboard or by deleting the folder and restarting, as the corrupt index guide describes. Do not back them up, and do not share one index folder between servers.
Ben-Gurion University’s site is a good example of how far Lucene can go: about 80,000 pages, a global search grouped by content type and more than ten dedicated search pages with their own filters, all on Lucene, plus a custom page-level cache that invalidates only pages depending on changed content.
Logs, temp files and other folders
- Logs: Umbraco uses Serilog and writes JSON files to
umbraco/Logs, named with machine name and date, for exampleUmbracoTraceLog.WEB01.20261009.json, as described in the logging docs. The back-office Log Viewer reads these files. In containers, add a sink that ships logs elsewhere. - Temp:
umbraco/Data/TEMPholds working files, and uploads go toumbraco/Data/TEMP/TemporaryFile/unlessTemporaryFileUploadLocationsays otherwise.Umbraco:CMS:Hosting:LocalTempStorageLocationset toEnvironmentTempmoves temp data to the OS temp folder. - SQLite file:
umbraco/Data/Umbraco.sqlite.dbwhen you use SQLite. - Configuration:
appsettings.jsonandappsettings.{Environment}.json, overridable by environment variables such asUmbraco__CMS__Global__MainDomLock. - Templates and code: Razor views in
/Viewsand compiled code in the deployment. Back-office extensions ship as static files from packages orApp_Plugins.
Schema as files: Umbraco Deploy and uSync
Document Types, Data Types and templates live in the database, which makes them awkward to move between environments. Two tools serialize them to disk so they can go into Git:
- Umbraco Deploy writes schema items to
umbraco/Deploy/Revision. The Deploy docs explain that these files must be committed, and a deployment trigger extracts them into the target environment. Umbraco Cloud uses Deploy by default. - uSync, a widely used community package, exports schema and optionally content to XML files in a uSync folder at the project root and imports them on another environment.
Either way, the database stays the runtime source of truth and the files are the transport format.
What to back up
A restorable Umbraco backup has three parts:
- The database. Full SQL Server backups plus transaction log backups, or the managed point-in-time restore of Azure SQL or Amazon RDS. Umbraco Cloud offers 35-day point-in-time recovery and lets project administrators download a
.bacpacfile, according to its backup documentation. - The media store. The
wwwroot/mediafolder or the blob container. Enable blob soft delete or versioning, or copy to a second region. - Code and configuration. The Git repository, including Deploy or uSync files, and the secrets from your vault.
Restore the database and media from the same point in time. A database restored to yesterday with today’s media is usually fine. The reverse leaves pages pointing at files that do not exist.
You do not need to back up Examine indexes, cmsContentNu separately (it is in the database anyway), logs or umbraco/Data/TEMP.
Implications for load balancing and cloud hosting
Once you run more than one instance, every item in the “on disk” column needs a decision. Umbraco’s load balancing guide covers the essentials:
- One database for all instances, with SQL Server. Servers coordinate through
umbracoServerandumbracoCacheInstruction. - Server roles: one
SchedulingPublisher(usually the back-office instance) runs scheduled publishing, and front-end instances areSubscribers. Set roles explicitly instead of relying on election. - Shared media: blob storage or a central file share, never per-server folders.
- Per-server indexes: on Azure App Service the Azure Web Apps guidance recommends
SyncedTempFileSystemDirectoryFactoryfor the back-office app,TempFileSystemDirectoryFactoryfor scaled public instances,LocalTempStorageLocation: EnvironmentTemp, andMainDomLock: FileSystemMainDomLock. - Shared Data Protection keys and a distributed cache for session and TempData, or users see validation and decryption errors when requests hop between servers.
- Stable machine identity in containers: from Umbraco 18.1,
Umbraco:CMS:Hosting:MachineIdentifierlets a restarted container resume cache sync instead of rebuilding caches and indexes.
Ben-Gurion University’s platform shows how this maps to AWS. The site runs in containers on ECS Fargate behind a load balancer, with Amazon RDS for SQL Server, Amazon S3 for storage and container images in Amazon ECR. Because the database and files were already outside the containers, the team could move from Azure to AWS with zero interruption to the public site. We wrote up that process in Azure to AWS migration without downtime.
Checklist for architects
- Confirm the database engine and collation: SQL Server, case-insensitive.
- Set an explicit
ContentVersionCleanupPolicyand check the size ofumbracoPropertyDataandumbracoContentVersionevery quarter. - Move media to blob storage before you add a second instance.
- Decide where Examine indexes live per environment, and make index rebuilds part of the deployment runbook.
- Ship logs off the box.
- Keep schema in Git with Deploy or uSync.
- Test a full restore, database plus media, at least once a year.
If you are planning hosting changes, an upgrade or a scale-out, our Umbraco development team and Umbraco support service can review your current setup, and our cloud and DevOps engineers handle the infrastructure side. For version planning, see Umbraco 13 vs 17.
- DatabaseBack up
Content, versions, schema, users, members, Forms.
- Media storeBack up
wwwroot/media or Azure Blob Storage.
- Source control and secretsIn Git
Code, views, config, Deploy or uSync files.
- Caches and indexesRebuildable
Published cache and Examine indexes.
- Umbraco instance ⇄ L0: converted content, unbounded by default In-process memory
- Umbraco instance ⇄ Optional L2 such as Redis, shared across servers Distributed cache
- Umbraco instance ⇄ Serialized published and draft data in the database cmsContentNu




