skip to content

In Redis Pub/Sub, what does the PSUBSCRIBE command do that SUBSCRIBE does not, and what exactly does a subscribed client receive when a published message matches?

level: juniorimportance: should knowfreq 38%

answer

  1. glob, not regex: * ? [a-c] and backslash escape
  2. pmessage = 4 parts, message = 3 parts
  3. element order: pattern, then real channel
  4. matched at publish time against the literal channel
  5. confirmation count = total subscriptions on the connection

basics

~20 s

PSUBSCRIBE registers a glob pattern (* ? [ab]) instead of an exact channel name. When a publish matches, the client gets a pmessage push with four parts: the literal 'pmessage', the pattern that matched, the actual channel published to, and the payload.

solid answer

~50 s

`SUBSCRIBE` registers exact channel names; `PSUBSCRIBE` registers glob-style patterns, matched at publish time against the literal channel name the publisher used. The glob syntax supports `*` (any sequence, including `.` since it is not special), `?` (one character), `[abc]` / `[a-c]` character classes, and `\` to escape a literal `*` or `?`. The delivery differs too. An exact subscription delivers a three-element push: `message`, channel, payload. A pattern subscription delivers a four-element push: `pmessage`, the **pattern** that matched, the **actual channel**, then the payload. That third element is essential, since `events.*` tells you nothing about whether this was `events.login` or `events.logout`. Matching only ever happens against published channel names; patterns never match other patterns, and a publisher does nothing special. In RESP2 a subscribed connection may only issue subscribe/unsubscribe, `PING`, `RESET` and `QUIT`; RESP3 removes that restriction because pushes are a distinct message type.

code

text · 16 lines
text
# subscriber connection
PSUBSCRIBE news.*
1) "psubscribe"
2) "news.*"
3) (integer) 1        # total subscriptions on this connection

# elsewhere: PUBLISH news.sports "goal"
1) "pmessage"         # 4 elements for a pattern match
2) "news.*"           # the pattern that matched
3) "news.sports"      # the ACTUAL channel published to
4) "goal"

# for comparison, an exact SUBSCRIBE news.sports delivers 3 elements:
1) "message"
2) "news.sports"
3) "goal"

go deeper

for a junior

Say PSUBSCRIBE takes a glob pattern instead of a literal channel, and that matches arrive as pmessage carrying both the pattern and the real channel.

for a middle

Add the glob details (* spans dots, ? and character classes, backslash escaping), the confirmation push with its cumulative count, and RESP2 subscriber-mode restrictions.

for a senior

Connect it to real use such as keyspace notifications, and volunteer the caveats: publish-time matching cost, duplicate delivery on overlap, and at-most-once delivery with no replay.

for a principal

Discuss channel-naming conventions as an interface contract, when a pattern tap is acceptable at all given loss on disconnect, and the operational cost of pattern fanout at high publish rates.

## Exact subscriptions versus pattern subscriptions Redis Pub/Sub routes messages by channel name. `SUBSCRIBE news.sports` registers interest in one literal name; a `PUBLISH news.sports hello` is delivered to every client holding that exact subscription. `PSUBSCRIBE news.*` instead registers a **pattern**, and at publish time Redis tests the published channel name against every registered pattern. The important direction: matching goes pattern-versus-published-channel. Patterns are never matched against other clients' subscriptions, and publishers are unaware that patterns exist. There is also no channel registry: channels are not created or declared, they are just names carried by `PUBLISH`, so a pattern can match a channel that has never been used before and will start delivering the moment someone publishes to it. ## Glob syntax The pattern language is Redis's glob style, the same family used by `KEYS` and `SCAN MATCH`: - `*` matches any sequence of characters, including none, and including dots or colons, since those are ordinary characters. `news.*` matches `news.sports` and also `news.sports.football`. - `?` matches exactly one character. - `[abc]` matches one character from the set; ranges like `[a-c]` and negation `[^a]` are supported. - `\` escapes the next character, so `\*` matches a literal asterisk. There is no regular-expression support, no alternation, and no way to say 'one segment only'. If you need segment-scoped matching, encode it in the naming convention rather than expecting the glob to understand hierarchy. ## The pmessage payload shape This is the part interviewers probe, because it trips people writing a client by hand: - Exact subscription delivery: `message`, `<channel>`, `<payload>` (three elements). - Pattern subscription delivery: `pmessage`, `<pattern>`, `<channel>`, `<payload>` (four elements). The pattern is included so a client subscribed to several patterns can tell which one fired; the channel is included because the pattern itself does not identify the concrete source. Code that blindly reads element 2 as the channel will read the pattern instead, a classic bug when a handler is shared between `SUBSCRIBE` and `PSUBSCRIBE` paths. Subscribing itself produces a confirmation push too: `psubscribe`, `<pattern>`, `<count>`, where `count` is the client's **total** subscription count (exact channels plus patterns), not a per-pattern number. `PSUBSCRIBE a.* b.*` produces two confirmation pushes, with counts 1 and 2. ## Subscriber mode Under RESP2, once a connection holds any subscription it enters subscriber mode: only `SUBSCRIBE`, `UNSUBSCRIBE`, `PSUBSCRIBE`, `PUNSUBSCRIBE`, `SSUBSCRIBE`, `SUNSUBSCRIBE`, `PING`, `RESET` and `QUIT` are accepted. So a client cannot do a `GET` on the same connection while pattern-subscribed, which is why libraries dedicate a connection to Pub/Sub. RESP3 (Redis 6.0 and later, opt-in via `HELLO 3`) tags pushes as a separate protocol type, so a RESP3 connection can interleave ordinary commands with subscriptions. ## Typical uses Pattern subscriptions shine when the channel namespace is hierarchical and consumers care about a subtree: `orders.*` for an audit tap, `metrics.host-*` for a fleet view. The most common real-world example is **keyspace notifications**: with `notify-keyspace-events` enabled, Redis publishes to channels like `__keyevent@0__:expired`, and consumers pick them up with `PSUBSCRIBE __keyevent@0__:*` or `PSUBSCRIBE __keyspace@0__:user:*`. That works precisely because the channel name is generated per key/event and cannot be enumerated in advance. ## Limits to state up front A pattern subscription inherits every Pub/Sub property: delivery is at-most-once and only to clients connected at publish time, with no history, no acknowledgement, and no replay after a reconnect. Patterns widen *what* you receive, not the durability of receiving it. They also add cost on the publish path, since every registered pattern is tested per publish, and they can deliver the same message twice to one client when the client also holds an overlapping subscription. ## What an interviewer is listening for The four-element `pmessage` shape (especially that both the pattern and the concrete channel are present), the glob syntax with `*` not respecting delimiters, and the awareness that matching is evaluated at publish time against the literal channel name.

  • Does the pattern news.* match the channel news.sports.football?
    Yes. The glob * matches any sequence of characters and treats the dot as an ordinary character, so it spans delimiters. Redis globs have no notion of hierarchy or segments, so if you need single-segment matching you must encode it another way, for example with a character-class or fixed-length pattern, or by choosing channel names that make the distinction explicit.

saying these in an interview costs you the question

  • Reading element 2 of a pmessage as the channel when it is the pattern
  • Assuming * stops at a dot or colon like some other messaging systems
  • Thinking patterns are matched against other clients' channel subscriptions rather than the published channel
  • Believing a pattern subscription buffers or replays messages sent while disconnected
  • Expecting full regular expressions instead of glob syntax

context