Skip to content

Bug: Multi-tenant Postgres Transport Always Uses Wrong Sender Due to database.Name Being Always "Default" #1901

@naveenpatilcbit

Description

@naveenpatilcbit

Bug: Multi-tenant Postgres Transport Always Uses Wrong Sender Due to database.Name Being "Default"

Summary

When using Wolverine with a multi-tenant Postgres setup (Postgres as both the application database and the transport), the transport sender resolution fails because all tenant-specific IMessageDatabase objects get the same Name value: "Default".

Since MultiTenantedQueueSender resolves senders using:

_byDatabase.TryFind(database.Name, out sender)

and database.Name is never set uniquely per tenant, every tenant’s database ends up with:

Name = "Default"

This causes Wolverine to reuse the wrong sender when processing outgoing envelopes for other tenants.

What Actually Happens

  1. First tenant request arrives.
    Wolverine creates a PostgresqlQueueSender for Tenant 1 and stores it in the dictionary:

    "Default" => Sender(Tenant1)
    
  2. Second tenant request arrives.
    A new sender for Tenant 2 is created, but the key is again "Default", so the dictionary lookup returns the existing sender for Tenant 1.

  3. The Durability Agent attempts to process envelopes using the wrong database connection, leading to errors like:

    InvalidOperationException: No matching outgoing envelope
    Sending agent for postgresql://shipment_queue/ is latched
    

As a result, Wolverine runs queue operations against the wrong tenant database.

Root Cause

PostgresqlTenantedMessageStore.buildTenantStoreForConnectionString() does not assign a unique name to each tenant’s IMessageDatabase.

Because of this:

  • All tenant DB sources collapse into a single dictionary entry.
  • Wolverine always reuses the first sender created.
  • Envelope movement fails because the query runs against the wrong database.

Expected Behavior

Each tenant's IMessageDatabase should have a unique, stable name, such as:

  • The tenant id, or
  • A normalized connection string identifier, or
  • A configured logical name.

This ensures MultiTenantedQueueSender correctly resolves the transport sender for the active tenant.

Actual Behavior

All tenants share the name "Default", causing:

  • Wrong sender lookup.
  • Wrong database connection usage.
  • Envelope transitions failing with InvalidOperationException: No matching outgoing envelope.

How to Reproduce

  1. Configure Wolverine with:
    • Multi-tenant application DB (different schemas or DB servers).
    • Multi-tenant Postgres transport.
  2. Send messages from Tenant 1 and Tenant 2.
  3. Observe:
    • Outbox inserts occur in the correct tenant DB.

    • The Durability Agent processes envelopes using the wrong tenant connection.

    • Errors like the following appear:

      InvalidOperationException: No matching outgoing envelope
      

Impact

Multi-tenant Postgres transport becomes effectively non-functional, because messages are always routed using the wrong database connection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions