MongoDB Setup
Minimal example to enable MongoDB persistence for Elsa Workflows, including connection configuration and index creation guidance.
This document provides a minimal, copy-pasteable example for configuring Elsa Workflows with MongoDB persistence.
Prerequisites
.NET 8.0 or later
MongoDB 4.4 or later
Elsa v3.x packages
NuGet Packages
dotnet add package Elsa
dotnet add package Elsa.MongoDb
dotnet add package MongoDB.DriverMinimal Configuration
Program.cs
using Elsa.Extensions;
var builder = WebApplication.CreateBuilder(args);
// Get connection string from configuration
var mongoConnectionString = builder.Configuration.GetConnectionString("MongoDb")
?? throw new InvalidOperationException("Connection string 'MongoDb' not found.");
builder.Services.AddElsa(elsa =>
{
// Configure workflow management (definitions, instances)
elsa.UseWorkflowManagement(management =>
{
management.UseMongoDb(mongo =>
{
mongo.ConnectionString = mongoConnectionString;
// Optional: Specify database name (defaults to 'elsa')
// mongo.DatabaseName = "elsa_workflows";
});
});
// Configure workflow runtime (bookmarks, inbox, execution logs)
elsa.UseWorkflowRuntime(runtime =>
{
runtime.UseMongoDb(mongo =>
{
mongo.ConnectionString = mongoConnectionString;
});
});
// Enable HTTP activities (optional)
elsa.UseHttp();
// Enable scheduling activities (optional)
elsa.UseScheduling();
// Enable API endpoints
elsa.UseWorkflowsApi();
});
var app = builder.Build();
// Map Elsa API endpoints
app.UseWorkflows();
app.Run();appsettings.json
{
"ConnectionStrings": {
"MongoDb": "mongodb://localhost:27017/elsa"
}
}With Authentication:
{
"ConnectionStrings": {
"MongoDb": "mongodb://username:password@localhost:27017/elsa?authSource=admin"
}
}Replica Set:
{
"ConnectionStrings": {
"MongoDb": "mongodb://node1:27017,node2:27017,node3:27017/elsa?replicaSet=rs0"
}
}Index Creation
MongoDB does not automatically create indexes. Create these indexes for production performance:
Using MongoDB Shell
// Connect to the elsa database
use elsa;
// Workflow Definitions
db.WorkflowDefinitions.createIndex({ "DefinitionId": 1 });
db.WorkflowDefinitions.createIndex({ "Name": 1 });
db.WorkflowDefinitions.createIndex({ "IsPublished": 1 });
db.WorkflowDefinitions.createIndex({ "IsLatest": 1 });
db.WorkflowDefinitions.createIndex({ "Version": 1 });
// Workflow Instances
db.WorkflowInstances.createIndex({ "CorrelationId": 1 });
db.WorkflowInstances.createIndex({ "Status": 1 });
db.WorkflowInstances.createIndex({ "SubStatus": 1 });
db.WorkflowInstances.createIndex({ "DefinitionId": 1 });
db.WorkflowInstances.createIndex({ "DefinitionVersionId": 1 });
db.WorkflowInstances.createIndex({ "UpdatedAt": -1 });
db.WorkflowInstances.createIndex({ "CreatedAt": -1 });
db.WorkflowInstances.createIndex({ "Status": 1, "DefinitionId": 1 });
// Bookmarks
db.Bookmarks.createIndex({ "Hash": 1 });
db.Bookmarks.createIndex({ "ActivityTypeName": 1, "Hash": 1 });
db.Bookmarks.createIndex({ "WorkflowInstanceId": 1 });
db.Bookmarks.createIndex({ "CorrelationId": 1 });
db.Bookmarks.createIndex({ "ActivityId": 1 });
// Activity Execution Records
db.ActivityExecutionRecords.createIndex({ "WorkflowInstanceId": 1 });
db.ActivityExecutionRecords.createIndex({ "ActivityId": 1 });
db.ActivityExecutionRecords.createIndex({ "StartedAt": -1 });
// Workflow Execution Log Records
db.WorkflowExecutionLogRecords.createIndex({ "WorkflowInstanceId": 1 });
db.WorkflowExecutionLogRecords.createIndex({ "Timestamp": -1 });
// Workflow Inbox Messages
db.WorkflowInboxMessages.createIndex({ "Hash": 1 });
db.WorkflowInboxMessages.createIndex({ "CorrelationId": 1 });
db.WorkflowInboxMessages.createIndex({ "CreatedAt": 1 }, { expireAfterSeconds: 604800 }); // TTL: 7 days (7 * 24 * 60 * 60 = 604800 seconds)
print("Indexes created successfully");Save as Script
Save the above as create-indexes.js and run:
mongosh "mongodb://localhost:27017/elsa" create-indexes.jsAdvanced Configuration
Custom Database and Collection Names
elsa.UseWorkflowManagement(management =>
{
management.UseMongoDb(mongo =>
{
mongo.ConnectionString = mongoConnectionString;
mongo.DatabaseName = "my_workflows";
// Optional: Custom collection name prefix
// mongo.CollectionNamingStrategy = name => $"elsa_{name}";
});
});Connection Pool Settings
Configure MongoDB driver settings for high-concurrency scenarios:
var mongoSettings = MongoClientSettings.FromConnectionString(mongoConnectionString);
mongoSettings.MaxConnectionPoolSize = 100;
mongoSettings.MinConnectionPoolSize = 10;
mongoSettings.WaitQueueTimeout = TimeSpan.FromSeconds(30);
mongoSettings.ConnectTimeout = TimeSpan.FromSeconds(10);
// Register the configured client
builder.Services.AddSingleton<IMongoClient>(new MongoClient(mongoSettings));
// Use the registered client
elsa.UseWorkflowManagement(management =>
{
management.UseMongoDb(mongo =>
{
mongo.ConnectionString = mongoConnectionString;
});
});Read Preference for Replicas
For read-heavy workloads with replica sets:
var mongoSettings = MongoClientSettings.FromConnectionString(mongoConnectionString);
mongoSettings.ReadPreference = ReadPreference.SecondaryPreferred;
builder.Services.AddSingleton<IMongoClient>(new MongoClient(mongoSettings));Mapping Considerations
Custom Activity Data
When storing custom data in activities, ensure it's BSON-serializable:
// Good: Simple types serialize automatically
public class MyActivityData
{
public string Name { get; set; }
public int Count { get; set; }
public DateTime Timestamp { get; set; }
}
// For complex types, ensure serialization works
public class ComplexData
{
public Dictionary<string, object> Properties { get; set; }
[BsonIgnore] // Exclude from persistence
public Func<Task> Callback { get; set; }
}BSON Serialization Settings
Elsa uses MongoDB driver conventions. For custom serialization needs:
// Register custom serializers before AddElsa
BsonSerializer.RegisterSerializer(new GuidSerializer(GuidRepresentation.Standard));
// Or use convention packs
var pack = new ConventionPack
{
new CamelCaseElementNameConvention(),
new IgnoreExtraElementsConvention(true)
};
ConventionRegistry.Register("ElsaConventions", pack, t => true);TTL Collections
MongoDB supports TTL (Time-To-Live) indexes for automatic document expiration:
// Auto-delete workflow execution logs after 30 days
db.WorkflowExecutionLogRecords.createIndex(
{ "Timestamp": 1 },
{ expireAfterSeconds: 2592000 } // 30 days
);
// Auto-delete completed workflow instances after 60 days
// Note: Only works if you have a dedicated TTL field
db.WorkflowInstances.createIndex(
{ "ExpiresAt": 1 },
{ expireAfterSeconds: 0 } // Expire at the ExpiresAt time
);Troubleshooting
Connection Issues
Error: Unable to connect to server
Solutions:
Verify MongoDB is running:
mongosh --eval "db.runCommand({ping: 1})"Check connection string format
Verify network connectivity and firewall rules
For replica sets, ensure all nodes are accessible
Error: Authentication failed
Solutions:
Verify username/password
Check
authSourceparameter in connection stringEnsure user has appropriate roles:
readWriteon the elsa database
Performance Issues
Slow queries:
Verify indexes are created:
db.collection.getIndexes()Use explain plans:
db.collection.find({...}).explain("executionStats")Check for collection scans in slow query logs
High memory usage:
Review connection pool settings
Consider adding a TTL index for log collections
Implement retention policies for old workflow instances
Logging
Enable MongoDB driver logging:
{
"Logging": {
"LogLevel": {
"MongoDB": "Debug"
}
}
}Related Documentation
Persistence Guide — Overview and provider comparison
Indexing Notes — Detailed indexing guidance
MongoDB Documentation — Official MongoDB docs
Last Updated: 2025-11-28
Last updated