Topic Filters

Filters let you narrow message delivery to specific entities within a topic. Instead of receiving all updates, subscribe with filters and only get the messages you care about.

Why Filters?

Without filters, subscribing to a topic delivers every message published to it. For a dashboard showing 3 bookings out of thousands, this means receiving updates for all bookings and discarding most of them client-side.

Filters solve this at the infrastructure level. Subscribe to bookings with filters ["booking_1", "booking_2"] and only updates for those two bookings are delivered. When the user navigates to different bookings, swap filters dynamically — no resubscribe needed.

How It Works

Each filter value becomes a separate subscription at the infrastructure level, so filtering happens before messages reach your client — not by inspecting message payloads. This means zero wasted bandwidth.

No filters (wildcard — receives everything on the topic):
subscribe("bookings")
With filter — only receives matching updates:
subscribe("bookings", { filters: ["booking_1"] })
Publish targeting filtered subscribers:
publish("bookings", data, { filter: "booking_1" })
Publish without filter:
publish("bookings", data) // only wildcard subscribers receive this

Subscribe with Filters

Pass a filters array when subscribing to a topic:

import { NoLag } from '@nolag/js-sdk'

const client = NoLag('your_access_token')
await client.connect()

const room = client.setApp('dashboard').setRoom('ops')

// Subscribe with filters — only receive updates for these bookings
room.subscribe('bookings', {
  filters: ['booking_1', 'booking_2']
})

// Listen for messages (only matching filters arrive)
room.on('bookings', (data, meta) => {
  console.log('Booking update:', data)
  console.log('Filter:', meta.filter)  // e.g. 'booking_1'
})

Dynamic Filter Management

Change filters at any time without unsubscribing and resubscribing. New filters are subscribed before old ones are removed to minimize message gaps.

// Replace all filters (full swap)
room.setFilters('bookings', ['booking_3', 'booking_4'])

// Add filters to existing set
room.addFilters('bookings', ['booking_5'])
// Now active: ['booking_3', 'booking_4', 'booking_5']

// Remove specific filters
room.removeFilters('bookings', ['booking_3'])
// Now active: ['booking_4', 'booking_5']

// Remove all filters (switch to wildcard — receives everything)
room.setFilters('bookings', [])

Publishing with Filters

Specify a filter when publishing to target specific subscribers:

// Publish to a specific filter
room.emit('bookings', { status: 'confirmed' }, {
  filter: 'booking_1'
})
// Only subscribers with 'booking_1' in their filters receive this

// Publish without a filter
room.emit('bookings', { type: 'system_update' })
// Only wildcard subscribers (no filters) receive this
// Filtered subscribers do NOT receive filterless publishes
Important: Messages published without a filter are only delivered to wildcard (no-filter) subscribers. Filtered subscribers do NOT receive filterless publishes. Use a separate topic for broadcasts if needed.

Example: Real-time Dashboard

The most common use case for filters is dashboards where users view a subset of entities that update in real-time:

// Real-time dashboard: user views 3 bookings out of thousands
const room = client.setApp('dashboard').setRoom('ops')

// Subscribe only to the bookings currently visible
const visibleBookingIds = ['booking_42', 'booking_87', 'booking_153']
room.subscribe('bookings', {
  filters: visibleBookingIds
})

room.on('bookings', (data, meta) => {
  updateBookingCard(meta.filter, data)
})

// User navigates to a different page of bookings
function onPageChange(newBookingIds: string[]) {
  room.setFilters('bookings', newBookingIds)
}

// User opens a booking detail view — add it to filters
function onBookingOpen(bookingId: string) {
  room.addFilters('bookings', [bookingId])
}

// User closes a booking detail view — remove it
function onBookingClose(bookingId: string) {
  room.removeFilters('bookings', [bookingId])
}

Filter Rules

  • Max 100 filters per topic per connection
  • Filter values must not contain /, #, or + (reserved characters)
  • Filters are persisted — on reconnect, your filters are automatically restored
  • Filters work with load balancing — each filter topic uses the shared subscription group
  • Setting filters to an empty array switches back to wildcard mode (receives everything)

Filters vs Wildcards

ScenarioApproach
Receive all messages on a topicSubscribe without filters (wildcard)
Receive updates for specific entitiesSubscribe with filters
Change which entities to tracksetFilters / addFilters / removeFilters
Broadcast to all subscribersUse a separate topic (filtered subscribers won't receive filterless publishes)

Next Steps