Skip to content

Add configurable :keys option for the underlying Registry#210

Open
studzien wants to merge 1 commit intophoenixframework:mainfrom
studzien:registry-keys-option
Open

Add configurable :keys option for the underlying Registry#210
studzien wants to merge 1 commit intophoenixframework:mainfrom
studzien:registry-keys-option

Conversation

@studzien
Copy link
Copy Markdown
Contributor

Summary

Adds a :keys option to Phoenix.PubSub, forwarded to the underlying Registry. Defaults to :duplicate (no behavior change). Accepts :unique, :duplicate, {:duplicate, :pid}, or {:duplicate, :key}.

{Phoenix.PubSub, name: :my_pubsub, keys: {:duplicate, :key}}

Motivation

{:duplicate, :key}, added in elixir-lang/elixir#14654 (which cites #198 as motivation), shards by topic key — better for workloads with many topics and few subscribers per topic, since key-based lookups touch a single partition. The default :duplicate (≡ {:duplicate, :pid}) is still best when topics have many subscribers each.

See Registry.start_link/1 for trade-offs.

Notes

  • Tuple forms require Elixir v1.19+.
  • :unique is accepted but rarely useful for pub/sub (caps each topic at one subscriber).
  • 3 new tests cover :unique rejection, :duplicate default delivery, and :unique broadcast.

Comment thread lib/phoenix/pubsub.ex Outdated
one of `:unique`, `:duplicate`, `{:duplicate, :pid}`, or
`{:duplicate, :key}` (defaults to `:duplicate`, which is equivalent
to `{:duplicate, :pid}`). With `:unique`, subscribing the same
process to the same topic twice returns
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought unique would only allow a single process per topic, no? It probably doesn't make sense? Perhaps the option should be group_by: :pid | :key?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's right. It doesn't make much sense, but I can think of scenarios where it does (like limiting to one subscriber per user topic).
The main reason I went with just passing the option directly to Registry was that we can't use the {:duplicate, _} form in Elixir < 1.19 (it crashes in CI runs).
Would making an Elixir-dependent test be the way to go here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default to :duplicate and use the tuple only of group_by is given. Let’s not support unique :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. Also added a test dependent on the Elixir version, but maybe we don't need that

Selects how the underlying Registry partitions subscriptions. Defaults
to :pid (current behavior). Accepts :pid or :key.

  - :pid (default) groups entries by subscriber pid; best when topics
    have many subscribers each. Translates to keys: :duplicate.
  - :key groups entries by topic so key-based lookups touch a single
    partition; best when there are many topics with few subscribers
    each. Translates to keys: {:duplicate, :key}, which requires
    Elixir 1.19+ (see elixir-lang/elixir#14654).

Invalid values raise ArgumentError at supervisor start.

Refs: phoenixframework#198
@studzien studzien force-pushed the registry-keys-option branch from 81a7706 to 971441a Compare April 30, 2026 11:20
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