Skip to content

Allow multiple flushes from EF Core DbContextOutbox#3072

Merged
jeremydmiller merged 1 commit into
JasperFx:mainfrom
Ferchke7:feat-dbcontext-multiflushmode
Jun 11, 2026
Merged

Allow multiple flushes from EF Core DbContextOutbox#3072
jeremydmiller merged 1 commit into
JasperFx:mainfrom
Ferchke7:feat-dbcontext-multiflushmode

Conversation

@Ferchke7

Copy link
Copy Markdown
Contributor

Adds a per-call MultiFlushMode option to the EF Core outbox save/flush API:

await outbox.SaveChangesAndFlushMessagesAsync(
    MultiFlushMode.AllowMultiples,
    cancellationToken);

The default behavior is unchanged. MessageContext.MultiFlushMode still defaults to OnlyOnce.

Use Cases

Chunked publishing from Minimal APIs or MVC controllers

A common pattern is to publish a large number of messages in chunks so each chunk is committed and flushed separately:

app.MapPost("/send-bulk", async (
    IDbContextOutbox<AppDbContext> outbox,
    IReadOnlyList<CreateInvoiceCommand> commands,
    CancellationToken cancellationToken) =>
{
    foreach (var chunk in commands.Chunk(500))
    {
        foreach (var command in chunk)
        {
            await outbox.PublishAsync(command);
        }

        await outbox.SaveChangesAndFlushMessagesAsync(
            MultiFlushMode.AllowMultiples,
            cancellationToken);
    }
});

Without AllowMultiples, only the first flush is honored on the scoped outbox instance.

For example, with 2,000 messages split into 4 chunks of 500:

  • chunk 1: 500 messages flushed
  • chunk 2: flush skipped
  • chunk 3: flush skipped
  • chunk 4: flush skipped

Result: only the first 500 messages are flushed.

Import jobs that save progress per batch

Background import jobs often process records in batches and commit progress after each batch:

public async Task ImportAsync(
    IDbContextOutbox<AppDbContext> outbox,
    IReadOnlyList<CustomerRow> rows,
    CancellationToken cancellationToken)
{
    foreach (var batch in rows.Chunk(100))
    {
        foreach (var row in batch)
        {
            var customer = Customer.From(row);

            outbox.DbContext.Customers.Add(customer);

            await outbox.PublishAsync(new CustomerImported
            {
                CustomerId = customer.Id
            });
        }

        await outbox.SaveChangesAndFlushMessagesAsync(
            MultiFlushMode.AllowMultiples,
            cancellationToken);
    }
}

Each batch saves EF Core changes and flushes the messages produced by that batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants