Skip to content

The search box in the website knows all the secrets—try it!

For any queries, join our Discord Channel to reach us faster.

JasperFx Logo

JasperFx provides formal support for Marten and other JasperFx libraries. Please check our Support Plans for more details.

Optimized Development Workflow

WARNING

The original "optimized development workflow" option introduced in Marten 4/5 was completely eliminated in Marten 8.0 (and Wolverine 4.0) in favor of the "Critter Stack" common option shown here.

The original point of Marten was to have a persistence option that mostly got out of your way and let developers just get things done without having to spend a lot of time fiddling with database scripts or ORM configuration. To that end, the default configuration for Marten is optimized for immediate developer productivity:

cs
var store = DocumentStore.For("connection string");

snippet source | anchor

In the configuration above, as needed, behind the scenes Marten is:

  1. Checking the underlying database to check if the existing database schema matches the in memory configuration for each document type and the event sourcing, then applies any necessary database migrations at runtime
  2. Generating and compiling dynamic code at runtime for each document type, compiled query type, the event sourcing, and some types of event projections

And that's (mostly) great at development time! However, the dynamic code compilation comes with a nontrivial cold start drag that's unsuitable for serverless architectures and some unnecessary sluggishness in automated testing sometimes. The automatic database migrations may be undesirable in production as it requires significant rights from the application to the underlying Postgresql database. Additionally, the automatic database migrations does require a little bit of in memory locking in the Marten code that has been problematic for folks using Marten from Blazor.

To allow for maximum developer productivity while using more efficient production options, use this option in Marten bootstrapping:

cs
using var host = await Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.AddMarten("connection string");

        // In a "Production" environment, we're turning off the
        // automatic database migrations and dynamic code generation
        services.CritterStackDefaults(x =>
        {
            x.Production.GeneratedCodeMode = TypeLoadMode.Static;
            x.Production.ResourceAutoCreate = AutoCreate.None;
        });
    }).StartAsync();

snippet source | anchor

When using this option, if IHostEnvironment.IsDevelopment() as it would be on a local developer box, Marten is using:

  • StoreOptions.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate to detect and apply database schema migrations as needed.
  • StoreOptions.GeneratedCodeMode = TypeLoadMode.Dynamic to generate dynamic code if necessary, or use pre-built types when they exist. This optimizes the development workflow to avoid unnecessary code compilations when the Marten configuration isn't changed.

At production time, that changes to:

  • StoreOptions.AutoCreateSchemaObjects = AutoCreate.None to short circuit any kind of automatic database change detection and migration at runtime. This is also a minor performance optimization that sidesteps potential locking issues.
  • StoreOptions.GeneratedCodeMode = TypeLoadMode.Static to only try to load pre-built types from what Marten thinks is the application assembly.

Released under the MIT License.