Configure the database
The journal, query journal, and snapshot store use the same database provider by default. In F#, choose
the provider with Fcqrs.connect and pass the connection to Fcqrs.actor.
open FCQRS.FSharp
let connection =
Fcqrs.connect FCQRS.Actor.DBType.Sqlite "Data Source=app.db;"
// An empty IConfiguration accepts the embedded Akka.NET defaults.
let config = Microsoft.Extensions.Configuration.ConfigurationBuilder().Build()
let loggerFactory = Microsoft.Extensions.Logging.LoggerFactory.Create(fun _ -> ())
let api = Fcqrs.actor config loggerFactory (Some connection) "MyCluster"
FCQRSFCQRS.FSharpIdiomatic-F# functional facade for FCQRS. Gives F# consumers the same one-call ergonomics the C# host-builder (HostExtensions.fs) gives C#, but with F# idioms: records-of-functions for the definitions, typed handles for the results, an explicit wiring pipeline, and plain helpers for saga side effects. It is a *pure addition* that wraps only the existing primitives (IActor.InitializeActor / SagaBuilder.initSimple / Query.init / InitializeSagaStarter / CreateCommandSubscription / Actor.api) and changes nothing in the C# interop layer or the core. open FCQRS.FSharp let api = Fcqrs.actor config loggerFactory (Some (Fcqrs.connect DBType.Sqlite conn)) "Cluster" let documents = Fcqrs.aggregate api { Name="Document"; Initial=...; Decide=...; Fold=... } let slugs = Fcqrs.aggregate api { Name="Slug"; Initial=...; Decide=...; Fold=... } let publication = Fcqrs.saga api (publicationDef documents.Factory slugs.Factory) Fcqrs.wireSagaStarters api [ publication ] let subs = Fcqrs.projection api (Projection.single 0 updateReadModel) // (Projection.multi when you must control which notifications publish) // send a command and await the matching aggregate reply: let! ev = documents.Send (Fcqrs.newCid()) (Fcqrs.aggregateId id) cmd (fun e -> ...)
connection: FCQRS.Actor.ConnectionFCQRS.FSharp.Fcqrsconnect: FCQRS.Actor.DBType -> string -> FCQRS.Actor.ConnectionBuild a SQLite/etc. Connection from a raw connection string (ShortString hidden).
SqliteSQLite using Microsoft.Data.Sqlite provider
FCQRS.ActorFCQRS.Actor.DBTypeRepresents the type of database connection
config: Extensions.Configuration.IConfigurationRootMicrosoft``.ctor``: unit -> unitExtensionsConfigurationBuild: unit -> Extensions.Configuration.IConfigurationRootBuilds an with keys and values from the set of providers registered in . An with keys and values from the registered providers.
loggerFactory: Extensions.Logging.ILoggerFactoryCreate: System.Action<Extensions.Logging.ILoggingBuilder> -> Extensions.Logging.ILoggerFactoryCreates new instance of configured using provided delegate. A delegate to configure the . The that was created.
LoggingMicrosoft.Extensions.Logging.LoggerFactoryProduces instances of classes based on the given providers.
api: FCQRS.Common.IActoractor: Extensions.Configuration.IConfiguration -> Extensions.Logging.ILoggerFactory -> FCQRS.Actor.Connection option -> string -> FCQRS.Common.IActorCreate the actor system from plain values (cluster name as a string).
SomeThe representation of "Value of type 'T" The input value. An option representing the value.
// C#: this host-builder overload is SQLite-backed.
using Microsoft.Extensions.DependencyInjection;
services.AddFcqrs("Data Source=app.db;", "MyCluster");
The C# AddFcqrs overload and ActorApi.Create currently create a SQLite connection definition. To use
another provider from a C# host, override the three persistence plugin connection and provider settings
through configuration as shown in the configuration reference.
Choose a provider
DBType supports these provider families:
| FCQRS value | Database |
|---|---|
Sqlite |
SQLite through Microsoft.Data.Sqlite |
PostgreSQL, PostgreSQL15 |
PostgreSQL |
SqlServer2012 through SqlServer2022 |
Microsoft SQL Server |
MySql |
MySQL through MySqlConnector |
Oracle |
Oracle Database |
Firebird |
Firebird |
DB2 |
IBM Db2 |
Changing the F# DBType configures all three persistence stores and enables table initialization:
open FCQRS.FSharp
let connection =
Fcqrs.connect FCQRS.Actor.DBType.PostgreSQL
"Host=localhost;Database=app;Username=app;Password=…"
FCQRSFCQRS.FSharpIdiomatic-F# functional facade for FCQRS. Gives F# consumers the same one-call ergonomics the C# host-builder (HostExtensions.fs) gives C#, but with F# idioms: records-of-functions for the definitions, typed handles for the results, an explicit wiring pipeline, and plain helpers for saga side effects. It is a *pure addition* that wraps only the existing primitives (IActor.InitializeActor / SagaBuilder.initSimple / Query.init / InitializeSagaStarter / CreateCommandSubscription / Actor.api) and changes nothing in the C# interop layer or the core. open FCQRS.FSharp let api = Fcqrs.actor config loggerFactory (Some (Fcqrs.connect DBType.Sqlite conn)) "Cluster" let documents = Fcqrs.aggregate api { Name="Document"; Initial=...; Decide=...; Fold=... } let slugs = Fcqrs.aggregate api { Name="Slug"; Initial=...; Decide=...; Fold=... } let publication = Fcqrs.saga api (publicationDef documents.Factory slugs.Factory) Fcqrs.wireSagaStarters api [ publication ] let subs = Fcqrs.projection api (Projection.single 0 updateReadModel) // (Projection.multi when you must control which notifications publish) // send a command and await the matching aggregate reply: let! ev = documents.Send (Fcqrs.newCid()) (Fcqrs.aggregateId id) cmd (fun e -> ...)
connection: FCQRS.Actor.ConnectionFCQRS.FSharp.Fcqrsconnect: FCQRS.Actor.DBType -> string -> FCQRS.Actor.ConnectionBuild a SQLite/etc. Connection from a raw connection string (ShortString hidden).
PostgreSQLPostgreSQL 9.3+
FCQRS.ActorFCQRS.Actor.DBTypeRepresents the type of database connection
Use SQLite for local development and deployments where one process owns the file. A multi-node cluster needs a database reachable by every node.
Do not commit production credentials in HOCON or source code. Supply them through the application's secret provider or environment-specific configuration.
Verify the connection
On a new database, start the application and confirm that journal, query journal, and snapshot tables are created. Send one command, stop the process, start it again, and send another command to the same aggregate id. The returned event version should advance, proving that recovery read the existing journal.
Then test the database account with automatic schema creation disabled if production policy requires pre-provisioned tables. The account still needs the read and write permissions required by the Akka.NET persistence plugins.
Other persistence settings
Change snapshot cadence with config:akka:persistence:snapshot-version-count, or use an aggregate or
saga SnapshotPolicy. The default is every 30 persisted events.
FCQRS merges application configuration over its embedded HOCON. The Configuration reference lists the merge order, plugin settings, runtime keys, and cluster overrides.