Knowledge base

A group of sending addresses with traffic shares

<virtual-mta-pool>
A pool is both traffic distribution and a shared settings scope

A pool lists sending addresses by name and distributes messages among them. Without shares — in rotation. With shares — in the given proportion, in steps of one tenth of a percent, and the shares must add up to 100.

A pool and a sending address share one namespace. Everything that can choose a sending address — a header, a pattern rule, an API call, a source default — chooses a pool in exactly the same way: by name. The sender does not need to know there is a group behind the name. The flip side: the engine does not resolve name collisions, it rejects the pool definition.

A pool is also a settings scope. Inside it you can declare a <domain> block and seven directives that go to each member. The manual names the resolution order directly: a recipient block inside a sending address inherits first from the pool, then from the node, and a member’s own line overrides the pool one.

Shares in tenths of a percent are a ready-made ramp. A new address at 0.1% versus an established one at 99.9% is the manual’s own example, and it is exactly the task for which a scheduler is usually written.

The main trap. A pool set as a source default always introduces itself with the name of the first member — without rotation. Traffic is distributed across all of them, but the name in the greeting is the same for all, and it matches the reverse record for at best one address.
What the Hub does. It writes the submission pool: in the working configuration all of the node’s sending addresses are listed in a common pool, and that pool is also the source default. But it uses it as a fallback: messages whose address was chosen by a header or a return address rule never reach the pool. The Hub does not write shares — it distributes across addresses itself, with the warm-up plan: the plan knows about stages, the reserve pool and stopping on the spam rate, while a weighted pool does not.
Recommended values

A pool has no values of its own — they are set by the directives inside. The choice made here is the distribution method:

How What you get When
without shares messages in rotation, equally the addresses are equal and equally warmed up
with shares a given proportion, in 0.1% steps introducing a new address, a canary share, a migration
with a plan instead of a pool distribution is decided at submission stages, per-receiver limits and stopping on the spam rate are needed

What can be moved to the pool so as not to repeat it for each member: a whole <domain> block and seven directives — cold-virtual-mta, domain-key, max-smtp-out, max-smtp-msg-rate, max-smtp-data-volume-rate, include-headers-from, suppression-lists.

The shares, the 0.1% step, the sum of 100, the shared namespace and the list of inherited directives all come from the manual. The comparison with the warm-up plan is ours.
Example configuration
# a canary share: the new address gets one message in a thousand
<virtual-mta-pool pool2>
    virtual-mta mta3 99.9    virtual-mta mta4 0.1
</virtual-mta-pool>
The manual’s example. The shares add up to exactly 100; otherwise the definition is invalid. The same pool can be written without numbers — then messages will go in rotation, equally.
yellow — — directive names, blue — blocks. They are highlighted the same way in the text of the card.
▲

Common mistakes and problems

what people get wrong and how it ends3 mistakes▶

Putting a sending address in two pools with recipient blocks

§ 3.3.13

What it costsThe manual directly calls this a configuration error: the member ends up with two conflicting inheritance sources for the same recipient domain.
How to spot itThe configuration is not applied, and the reason points to a pool that was not edited last.
How to do it rightKeep a member in one pool with recipient blocks. Move rules shared by several pools to the node level.

Setting a pool as the source default and expecting different names in the greeting

§ 3.3.1.35

What it costsThe name is taken from the first member and does not change. For the other addresses the greeting name diverges from their reverse records — even though each has its own name set in the configuration.
How to spot itRecipient-side checks complain about a name and reverse record mismatch for all pool addresses except one.
How to do it rightChoose the sending address by name — with a header or a pattern rule — and keep the pool as a fallback.

Setting shares that do not add up to a hundred

§ 3.3.13.1

What it costsThe sum must equal 100. A definition with a different sum is invalid, and this will surface when the configuration is applied, not when it is edited.
How to spot itThe reload fails after the shares are edited.
How to do it rightRecalculate the sum on every edit. The step is a tenth of a percent, so 99.9 and 0.1 add up, but 99.9 and 0.2 do not.
Compatibility
PowerMTA 6.0
described in the manual of this version · platform: any
The vendor does not state the first version for every directive — there is no note here. The name also appears in the 5.0 edition of the manual.
Inheritance
A pool is an intermediate level between the node and a sending address. Everything written in it goes to members; a member’s own line overrides the pool one. For recipient blocks the manual names the order directly: a block inside a sending address inherits first from the pool, then from the node. And it names the error: a sending address cannot belong to two pools that have <domain> blocks.
How to check on the node
Which pools are declared and who belongs to them is visible on the node:
pmta show vmtas
Two things are worth checking: that the pool name does not coincide with any sending address name, and that no member belongs to two pools with recipient blocks. The engine will reject the first, and the manual directly calls the second an error.
In the Hub
Cost of a mistake
disruptive: applying it interrupts the node
Scenarios
Capacity planning · Sending address rotation · Address warm-up