Fluens.Migrations 0.7.9

dotnet add package Fluens.Migrations --version 0.7.9
                    
NuGet\Install-Package Fluens.Migrations -Version 0.7.9
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Fluens.Migrations" Version="0.7.9" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Fluens.Migrations" Version="0.7.9" />
                    
Directory.Packages.props
<PackageReference Include="Fluens.Migrations" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Fluens.Migrations --version 0.7.9
                    
#r "nuget: Fluens.Migrations, 0.7.9"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Fluens.Migrations@0.7.9
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Fluens.Migrations&version=0.7.9
                    
Install as a Cake Addin
#tool nuget:?package=Fluens.Migrations&version=0.7.9
                    
Install as a Cake Tool

Fluens.Migrations

Provider-neutral FluentMigrator base classes and helpers for inbox/outbox tables, dead letters, HiLo sequences, and auditable/deletable columns. Zero Fluens dependencies.

Installation

dotnet add package Fluens.Migrations

# Plus exactly one provider package:
dotnet add package Fluens.Migrations.PostgreSql
# or
dotnet add package Fluens.Migrations.SqlServer

Usage

Runner registration

The provider is opted into from the AddFluens callback on FluentMigrator's own ConfigureRunner pipeline — never through a bespoke top-level method. rb.AddPostgres() / rb.AddSqlServer() (FluentMigrator's own provider registration) and .AddFluens(f => f.AddPostgres()) / .AddFluens(f => f.AddSqlServer()) (the Fluens conventions opt-in) are distinct extension targets — no ambiguity:

services.AddFluentMigratorCore()
    .ConfigureRunner(rb => rb
        .AddPostgres()                             // FluentMigrator's own provider registration
        .WithGlobalConnectionString(connectionString)
        .ScanIn(typeof(CreateOrdersSchema).Assembly).For.Migrations()
        .AddFluens(f => f.AddPostgres()));          // Fluens provider-conventions opt-in

Migration classes

Every FluensMigration subclass needs a forwarding constructor — Conventions is resolved by FluentMigrator's own constructor-injection support when the runner instantiates the migration, so a single, unchanged subclass creates the same schema on both providers:

public class CreateOrdersSchema : FluensMigration
{
    public CreateOrdersSchema(IMigrationProviderConventions conventions) : base(conventions) { }

    public override void Up()
    {
        Create.Schema("orders");

        Create.Table("orders").InSchema("orders")
            .WithColumn("id").AsGuid().PrimaryKey()
            .WithColumn("number").AsString(50).NotNullable()
            .WithColumn("total").AsDecimal().NotNullable()
            .WithAuditableAndDeletableColumns()
            .WithVersionColumn();

        CreateMessagingTables("orders"); // outbox + inbox + dead_letters
        CreateHiLoSequence("orders_hilo", "orders");
    }

    public override void Down()
    {
        DeleteMessagingTables("orders");
        DeleteHiLoSequence("orders_hilo", "orders");
        Delete.Table("orders").InSchema("orders");
    }
}

Helpers: WithAuditableColumns(), WithDeletableColumn(), WithAuditableAndDeletableColumns(), WithVersionColumn(), CreateOutboxTable(), CreateOutboxDeliveryTable(), CreateInboxTable(), CreateIngressOutboxTable(), CreateDeadLettersTable(), CreateMessagingTables(), CreateHiLoSequence(), DeleteOutboxTable(), DeleteOutboxDeliveryTable(), DeleteInboxTable(), DeleteIngressOutboxTable(), DeleteDeadLettersTable(), DeleteMessagingTables(), DeleteHiLoSequence().

Messaging schema (ADR 20260530000001 / ADR 20260530000002 / ADR 20260729000001)

All four messaging tables carry the serialized envelope blob (non-nullable; ADR 20260530000001 — replaces the bare context column) plus the denormalized routing columns (partition_key, priority, and on outbox also available_at) so the partial pending indexes can sort / filter on real columns. Each table has a partial pending index emitted via Conventions.ApplyFilter(<index>.WithOptions(), "<predicate>") — the registered provider package's .Filter(...) extension — so the hot fetch scans only in-flight rows:

  • outbox — the terminal marker is sent_at (renamed from the legacy published_at flag; ADR 20260530000002). Message-TTL columns expires_at (non-nullable, computed from (available_at ?? created_at) at write) and expired_at (nullable, set in place on TTL expiry — the row is never deleted, only marked). Also carries mint_seq (bigint, non-nullable, default 0 — a provider-neutral monotonic mint-time key derived from id's embedded GUIDv7 timestamp; ADR 20260729000001). Partial ix_outbox_pending (WHERE sent_at IS NULL) over (sent_at, priority DESC, mint_seq).
  • inbox — composite primary key (message_id, handler_type) (one row per subscribing handler). Also carries mint_seq (same shape as outbox, derived from message_id) and adds next_retry_at (stage-2 retry schedule). Partial ix_inbox_pending (WHERE processed_at IS NULL) over (handler_type, partition_key, priority DESC, mint_seq).
  • ingress_outbox — primary key message_id (boundary dedup). Partial ix_ingress_pending (WHERE processed_at IS NULL) over received_at.
  • dead_letters — adds the why-columns handler_type, partition_key, failure_code, exception_type, attempt_history (Conventions.JsonColumnTypejsonb on PostgreSQL, nvarchar(max) on SQL Server), and the replay marker replayed_at.

No upgrade (AddColumn) migration ships for mint_seqCreateOutboxTable/CreateInboxTable are create-table helpers only, so a consumer upgrading an already-deployed schema authors their own AddColumn("mint_seq").AsInt64().NotNullable().WithDefaultValue(0) step plus the corresponding index rebuild (ADR 20260729000001).

CreateOutboxDeliveryTable(schema) creates the per-destination delivery table (one row per (outbox_id, destination_app) pair) with a unique ix_outbox_delivery_outbox_dest index on (outbox_id, destination_app) for re-fan-out idempotency, an ix_outbox_delivery_destination_app index, and the partial ix_delivery_pending (WHERE delivered_at IS NULL AND expired_at IS NULL) over (expires_at, destination_app); CreateMessagingTables creates it alongside outbox/inbox in the module schema. CreateIngressOutboxTable(schema = "shared") creates the single staging table into which a peer-delivered batch is written atomically before acking.

Provider-specific column types

Use Fluens.Migrations.PostgreSql or Fluens.Migrations.SqlServer for provider-specific column types — independent of which IMigrationProviderConventions is registered for the run:

using Fluens.Migrations.PostgreSql; // AsCitext(), AsTimestampTz()

Create.Table("customers").InSchema("orders")
    .WithColumn("id").AsInt32().PrimaryKey().Identity()
    .WithColumn("email").AsCitext().NotNullable()         // case-insensitive text
    .WithColumn("created_at").AsTimestampTz().NotNullable(); // timestamp with time zone
using Fluens.Migrations.SqlServer; // AsNVarCharMax(), AsDateTimeOffset2()

Create.Table("customers").InSchema("orders")
    .WithColumn("id").AsInt32().PrimaryKey().Identity()
    .WithColumn("notes").AsNVarCharMax().Nullable()             // unbounded Unicode text
    .WithColumn("created_at").AsDateTimeOffset2().NotNullable(); // timestamp with time zone

Helpers: Fluens.Migrations.PostgreSql.AsCitext() / .AsTimestampTz(); Fluens.Migrations.SqlServer.AsNVarCharMax() / .AsDateTimeOffset2().

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Fluens.Migrations:

Package Downloads
Fluens.Migrations.SqlServer

SQL Server provider for Fluens.Migrations — nvarchar(max) attempt_history column type, datetimeoffset column helper, and FluentMigrator.SqlServer partial-index filters. Opt in via rb.AddFluens(f => f.AddSqlServer()).

Fluens.Migrations.PostgreSql

PostgreSQL provider for Fluens.Migrations — jsonb attempt_history column type, citext/timestamptz column helpers, and FluentMigrator.Postgres partial-index filters. Opt in via rb.AddFluens(f => f.AddPostgres()).

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.7.9 39 9/11/2026
0.7.8 46 9/10/2026
0.7.7 45 9/10/2026
0.7.6 158 7/1/2026
0.7.5 135 6/22/2026
0.7.4 145 6/18/2026
0.7.2 119 6/18/2026
0.7.1 134 6/18/2026
0.6.6 269 3/11/2026
0.6.5 119 3/4/2026
0.6.4 111 3/4/2026
0.6.3 125 3/3/2026
0.6.2 125 3/2/2026
0.6.1 121 3/2/2026
0.6.0 116 3/1/2026
0.5.7 131 3/1/2026
0.5.6 120 3/1/2026
0.5.5 121 2/28/2026
0.5.4 123 2/28/2026
0.5.3 126 2/27/2026
Loading failed