# Runtime Modes

## Configuring the runtime mode

You can configure the runtime mode to optimize Umbraco for different development experiences and environments by setting `Umbraco:CMS:Runtime:Mode` to one of the available modes:

* `BackofficeDevelopment` (default)
* `Development`
* `Production`

This can be done via the `appsettings.json` file, environment variables, or any other .NET configuration provider (like Azure Key Vault/App Configuration). Although this setting affects how Umbraco behaves at runtime, some modes have prerequisites on how the project is built/published. Make sure to read the descriptions of each mode before changing this setting from the default `BackofficeDevelopment` mode, as incorrect configuration can result in your application not starting (by throwing a `BootFailedException`).

## BackofficeDevelopment mode

The `BackofficeDevelopment` mode is the default behavior for Umbraco: it does not optimize Umbraco for any specific environment and does not have any prerequisites. This mode allows for rapid development (without having to recompile/rebuild your project), including all development from within the backoffice.

## Development mode

The `Development` mode can be used when you're developing from an IDE (like Visual Studio, VS Code, or Rider) or the dotnet CLI (e.g. using `dotnet watch`). It is a recommended prerequisite if you want to use the `Production` mode in your production environment.

This mode disables in-memory ModelsBuilder generation and validates the following setting:

* `Umbraco:CMS:ModelsBuilder:ModelsMode` is **not set** to `InMemoryAuto`.

If you want to use the generated models, use `SourceCodeAuto` or `SourceCodeManual`, which requires manually recompiling the project after the models have changed (e.g. after updating Document Types, Media Types, Member Types, or Data Types). Razor views (`cshtml` files) will still be automatically compiled at runtime, allowing you to quickly iterate on the rendered output from templates, (macro) partial views, and view components.

The recommended approach to enable `Development` mode is to update the `appsettings.json` file with the following settings:

```json
{
    "Umbraco": {
        "CMS": {
            "Runtime": {
                "Mode" : "Development"
            },
            "ModelsBuilder":{
                "ModelsMode": "SourceCodeAuto"
            }
        }
    }
}
```

Ensure your models are generated by running Umbraco and navigating to **Settings** > **Models Builder** > **Generate models**. You can remove the following properties from your `csproj` project file to enable the compilation of Razor views (which also ensures your views do not contain compilation errors and is a prerequisite for enabling `Production` mode):

```xml
<RazorCompileOnBuild>false</RazorCompileOnBuild>
<RazorCompileOnPublish>false</RazorCompileOnPublish>
```

Fix any compilation errors you might get after this, e.g. if you accidentally referenced deleted models or properties. Running the application will still show the rendered content and you're now ready to optionally enable `Production` mode on your production environment.

{% hint style="info" %}
Ensure you have the `<CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>` property set in your `csproj` project file, so Razor views are always copied to the publish directory. This is required by the CMS to display the contents in the backoffice, for Forms to lookup custom theme views and for Deploy to be able to compare schemas (otherwise you'll get schema mismatches).
{% endhint %}

## Production mode

Use `Production` mode to ensure your production environment is running optimally by disabling development features and validating whether specific settings are configured to their recommended production values.

This mode disables both in-memory ModelsBuilder generation (see [Development mode](#development-mode)) and Razor (cshtml) runtime compilation. Production mode requires you to compile your views at build/publish time and enforces the following settings for optimal performance/security:

* The application is built/published in Release mode (with JIT optimization enabled), e.g. using `dotnet publish --configuration Release`;
* `Umbraco:CMS:WebRouting:UmbracoApplicationUrl` is set to a valid URL;
* `Umbraco:CMS:Global:UseHttps` is enabled;
* `Umbraco:CMS:RuntimeMinification:CacheBuster` is set to a fixed cache buster like `Version` or `AppDomain`;
* `Umbraco:CMS:ModelsBuilder:ModelsMode` is set to `Nothing`.

{% hint style="info" %}
To compile your views at build/publish time, remove the `<RazorCompileOnBuild>` and `<RazorCompileOnPublish>` properties from your project file (see the [Development mode](#development-mode) section). If you don't, Umbraco can't find the templates and will return 404 (Page Not Found) errors.
{% endhint %}

The recommended approach to enable `Production` mode is to update the `appsettings.Production.json` file (or create one) with the following settings:

```json
{
  "Umbraco": {
    "CMS": {
      "Runtime": {
        "Mode": "Production"
      },
      "Global": {
        "UseHttps": true
      },
      "ModelsBuilder": {
        "ModelsMode": "Nothing"
      },
      "WebRouting": {
        "UmbracoApplicationUrl": "https://<REPLACE_WITH_YOUR_PRIMARY_DOMAIN>/"
      }
    }
  }
}
```

Although you can still edit document types and views (if not running from the published output), changes won't be picked up until you've rebuilt your project or republished the application.

{% hint style="info" %}
Models won't be generated by ModelsBuilder (because the mode is set to `Nothing`), requiring you to do all your changes while in `Development` mode.\
\
As Models Builder is set to `Nothing`, the Models Builder dashboard is disabled in the backoffice of live environment.

<img src="https://3872888104-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgEH4FChbCn7eDDqREvdE%2Fuploads%2Fgit-blob-14492e61ab306748d331dee09c90a8fa1be221ed%2FModelsBuilderDisabledOnProduction.png?alt=media&#x26;token=c5de635a-60b2-4b25-861c-5df1d34ba46e" alt="" data-size="original">

\
Also, templates cannot be edited on live environment as runtime compilation is not enabled and is set to Production.

<img src="https://3872888104-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgEH4FChbCn7eDDqREvdE%2Fuploads%2Fgit-blob-f6379dc05f643810c68d60b58a9530dbfeb5626b%2FTemplatedCannotBeEditedWhenRuntimeIsProduction.png?alt=media&#x26;token=98354226-12c1-4695-af9d-47e406428ba0" alt="" data-size="original">
{% endhint %}

Also ensure the `UmbracoApplicationUrl` is updated to the primary URL of your production environment, as this is used when sending emails (password reset, notifications, health check results, etc.) and the keep-alive task.

{% hint style="info" %}
Static web assets are disabled when using Production mode, following [Microsoft guidance](https://learn.microsoft.com/en-us/aspnet/core/blazor/fundamentals/static-files?view=aspnetcore-7.0#static-files-in-non-development-environments). If you are running a non-Development environment using the Production runtime mode from source (non-published output), you will need to explicitly enable this. You can add the following line of code to your `Program.cs` file:

```csharp
builder.WebHost.UseStaticWebAssets();
```

This should not be used in a more typical production environment where you are hosting your application from published output.
{% endhint %}

## Customize/extend runtime mode validation

Validation of the above-mentioned settings is done when determining the runtime level during startup using the new `IRuntimeModeValidationService` and when it fails, causes a `BootFailedException` to be thrown. The default implementation gets all registered `IRuntimeModeValidators` to do the validation, making it possible to remove default checks and/or add your own (inherit from `RuntimeModeProductionValidatorBase`, if you only want to validate against the production runtime mode). The following validators are added by default:

* `JITOptimizerValidator` - Ensure the application is built/published in Release mode (with JIT optimization enabled) when in production runtime mode, e.g. using `dotnet publish --configuration Release`;
* `UmbracoApplicationUrlValidator` - ensure `Umbraco:CMS:WebRouting:UmbracoApplicationUrl` is configured when in production runtime mode;
* `UseHttpsValidator` - ensure `Umbraco:CMS:Global:UseHttps` is enabled when in production runtime mode;
* `RuntimeMinificationValidator` - ensure `Umbraco:CMS:RuntimeMinification:CacheBuster` is set to a fixed cache buster like `Version` or `AppDomain` when in production runtime mode;
* `ModelsBuilderModeValidator` - ensure `Umbraco:CMS:ModelsBuilder:ModelsMode` is not set to `InMemoryAuto` when in development runtime mode and set to `Nothing` when in production runtime mode.

The following example removes the default `UmbracoApplicationUrlValidator` and adds a new custom `DisableElectionForSingleServerValidator`:

```csharp
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Infrastructure.Runtime;
using Umbraco.Cms.Infrastructure.Runtime.RuntimeModeValidators;

public class RuntimeModeValidatorComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
        => builder.RuntimeModeValidators()
            .Remove<UmbracoApplicationUrlValidator>()
            .Add<DisableElectionForSingleServerValidator>();
}

public class DisableElectionForSingleServerValidator : IRuntimeModeValidator
{
    private readonly IOptionsMonitor<GlobalSettings> _globalSettings;

    public DisableElectionForSingleServerValidator(IOptionsMonitor<GlobalSettings> globalSettings) => _globalSettings = globalSettings;

    public bool Validate(RuntimeMode runtimeMode, [NotNullWhen(false)] out string? validationErrorMessage)
    {
        if (runtimeMode == RuntimeMode.Production && _globalSettings.CurrentValue.DisableElectionForSingleServer == false)
        {
            validationErrorMessage = "Disable primary server election (and support for load balancing) to improve startup performance.";
            return false;
        }

        validationErrorMessage = null;
        return true;
    }
}
```
