Services
Custom software developmentUmbraco developmentWeb developmentCRM developmentERP developmentAI & LLM integration.NET development & modernizationE-commerce developmentIntegrations & automationCloud & DevOpsMaintenance, support & project rescueDedicated teams & white-label
Our Work
Case studiesProducts
About Blog Contact
Umbraco

Where does Umbraco store data? Database, media, cache, indexes and logs explained

Umbraco keeps content, settings, users and versions in SQL Server or SQLite, media files on disk or in blob storage, and search indexes, logs and temp files in the umbraco folder. Here is where each piece lives and what it means for backups and scaling.

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:

  1. 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.
  2. 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.
  3. 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, plus umbracoExternalLogin and umbracoTwoFactorLogin.
  • Members: cmsMember, cmsMemberType and cmsMember2MemberGroup. Member properties use the same umbracoPropertyData table 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, and umbracoDomain for Culture and Hostnames.
  • Audit and logs: umbracoAudit and umbracoLog keep an audit trail of user actions. These are not the Serilog application logs.
  • Load balancing: umbracoServer registers instances and umbracoCacheInstruction queues cache refresh instructions for other servers.
  • Housekeeping: umbracoKeyValue stores migration state for Umbraco and packages, umbracoLock handles distributed locks, and the umbracoWebhook* 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 MaximumLocalCacheItems and the opt-in Umbraco.Cms.PublishedCache.HybridCache.Bounded package.
  • Optional distributed cache (L2): if you register a distributed cache such as Redis, entries are shared across servers. RemoteCacheDuration defaults to one year.
  • Database cache: serialized published and draft data for each item is stored in the cmsContentNu table. When a content type changes structurally, Umbraco rebuilds the affected cmsContentNu rows, and from 17.4 you can defer that rebuild with ContentTypeRebuildMode: "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:

  1. 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.
  2. Physical path outside the webroot. Set Umbraco:CMS:Global:UmbracoMediaPhysicalRootPath to a local or network path. Umbraco wires it into the web root file provider so image resizing still works.
  3. Azure Blob Storage. Install Umbraco.StorageProviders.AzureBlob, add .AddAzureBlobMediaFileSystem() to the Umbraco builder in Program.cs, and configure Umbraco:Storage:AzureBlob:Media:ConnectionString and ContainerName. The companion Umbraco.StorageProviders.AzureBlob.ImageSharp package stores resized image cache in blob storage too, by default in a /cache folder in the media container. See the Umbraco.StorageProviders repository.
  4. Amazon S3 or other stores. There is no official Umbraco S3 provider in that repository; you use a community package or implement IFileSystem yourself.
// 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 in umbraco/Data/TEMP/ExamineIndexes.
  • SyncedTempFileSystemDirectoryFactory: works on a copy in the process temp folder and syncs back to umbraco/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 example UmbracoTraceLog.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/TEMP holds working files, and uploads go to umbraco/Data/TEMP/TemporaryFile/ unless TemporaryFileUploadLocation says otherwise. Umbraco:CMS:Hosting:LocalTempStorageLocation set to EnvironmentTemp moves temp data to the OS temp folder.
  • SQLite file: umbraco/Data/Umbraco.sqlite.db when you use SQLite.
  • Configuration: appsettings.json and appsettings.{Environment}.json, overridable by environment variables such as Umbraco__CMS__Global__MainDomLock.
  • Templates and code: Razor views in /Views and compiled code in the deployment. Back-office extensions ship as static files from packages or App_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:

  1. 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 .bacpac file, according to its backup documentation.
  2. The media store. The wwwroot/media folder or the blob container. Enable blob soft delete or versioning, or copy to a second region.
  3. 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 umbracoServer and umbracoCacheInstruction.
  • Server roles: one SchedulingPublisher (usually the back-office instance) runs scheduled publishing, and front-end instances are Subscribers. 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 SyncedTempFileSystemDirectoryFactory for the back-office app, TempFileSystemDirectoryFactory for scaled public instances, LocalTempStorageLocation: EnvironmentTemp, and MainDomLock: 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:MachineIdentifier lets 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 ContentVersionCleanupPolicy and check the size of umbracoPropertyData and umbracoContentVersion every 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.

OSKI Engineering TeamSenior .NET, Umbraco and AI engineers

Written by the engineers who build and support OSKI client projects, reviewed by our CTO before publishing.

FAQ

Questions readers ask

Anything missing? Send us your question and an engineer will answer, usually within one business day.

Contact us
What database does Umbraco use?+

Umbraco supports Microsoft SQL Server, from SQL Server 2016 upward, and SQLite. Azure SQL is what Umbraco Cloud uses behind the scenes, and Amazon RDS for SQL Server works for self-hosted sites. SQLite is convenient for local development and very small sites, but SQL Server is the usual choice for production and is required in practice for load balancing.

Are Umbraco media files stored in the database?+

No. The database stores the media item, its metadata and the file path, while the file itself sits in wwwroot/media on the web server by default. You can move files to Azure Blob Storage with the Umbraco.StorageProviders.AzureBlob package or to another store through a custom IFileSystem, and Umbraco Cloud always uses Azure Blob Storage.

Where are Umbraco Examine indexes stored?+

By default Examine writes its Lucene indexes to umbraco/Data/TEMP/ExamineIndexes. The LuceneDirectoryFactory setting can move them to the process temp folder, which Umbraco recommends on Azure App Service. Indexes can be rebuilt from the database, so they do not need to be backed up.

Where are Umbraco logs stored?+

Umbraco logs through Serilog and writes JSON log files to umbraco/Logs, with the machine name and date in the file name. You can add other Serilog sinks such as Application Insights, Seq or Datadog, which is the better option on containers where the local disk disappears on restart.

What do I need to back up for an Umbraco site?+

Back up the SQL Server or SQLite database, the media store (wwwroot/media or the blob container), and the code repository with appsettings files and secrets kept elsewhere. Examine indexes, the published cache, logs and temp files can be rebuilt or are not needed for a restore.

Start a project

Tell us what you need to ship. We come back with a plan and a price.

A spec, a Figma file or three paragraphs is enough to start.

  1. First reply · from an engineer, not a sales rep
  2. 30-min call · with Roman, our CTO, to clarify scope
  3. After the call · a written proposal with plan, team and price
Roman Oleksuk
Roman Oleksuk, CTOPrefer to talk? Pick a slot in Roman's calendar
We reply from a human mailbox. No newsletters. Your brief stays under NDA on request. We use your details only to reply; see our privacy policy.