Topics
Understanding and working with topics in RevenProx.
What are Topics?
Topics are named channels that clients subscribe to. Events published to a topic are delivered to all subscribed clients.
Topic: "user-123-notifications"
│
├── Client A (web browser)
├── Client B (mobile app)
└── Client C (desktop app)
Topic Names
Format
Topic names are strings that appear in the URL path:
Examples:
- /events/notifications
- /events/user-123-updates
- /events/room-abc-chat
Best Practices
| Do | Don't |
|---|---|
| Use descriptive names | Use cryptic IDs alone |
| Include context (user, room) | Use overly long names |
| Use URL-safe characters | Include special characters |
| Be consistent | Mix naming conventions |
Good topic names:
Topic UUIDs
Internally, topics are identified by 128-bit UUIDs:
The UUID is derived by hashing the topic name, ensuring consistent mapping.
UUID in Webhook
Your verification webhook receives the topic UUID:
You can use this for topic-level authorization:
// Map topic names to UUIDs for authorization
const topicUUIDs = {
'admin-notifications': 'abc123...',
'public-updates': 'def456...'
};
function canAccessTopic(user, topicHex) {
const userTopics = getUserAllowedTopics(user);
return userTopics.some(name =>
hashToHex(name) === topicHex
);
}
Subscribing to Topics
Single Topic
Multiple Topics
Connect to each topic separately:
const topics = ['alerts', 'messages', 'updates'];
const connections = topics.map(topic =>
new EventSource(`/events/${topic}`)
);
Dynamic Topics
Generate topic names based on context:
function subscribeToUser(userId) {
return new EventSource(`/events/user-${userId}-updates`);
}
function subscribeToRoom(roomId) {
return new EventSource(`/events/room-${roomId}-chat`);
}
Topic Patterns
User-Specific Topics
Each user subscribes to their own topic for private updates.
Resource Topics
Track updates to specific resources.
Broadcast Topics
All clients receive the same events.
Room/Channel Topics
Group communication.
Topic Authorization
Control access to topics in your webhook:
User-Owned Topics
app.post('/verify', (req, res) => {
const { jwt: token, topic } = req.body;
const decoded = jwt.verify(token, JWT_SECRET);
// User can only access their own topics
const userTopicPrefix = hashUserId(decoded.sub);
const isOwner = topic.startsWith(userTopicPrefix);
res.json({
valid: isOwner,
user_id: decoded.sub,
expires_at: decoded.exp
});
});
Role-Based Access
app.post('/verify', (req, res) => {
const { jwt: token, topic } = req.body;
const decoded = jwt.verify(token, JWT_SECRET);
// Check role permissions
const topicName = uuidToTopicName(topic);
const requiredRole = getRequiredRole(topicName);
const hasAccess = decoded.roles.includes(requiredRole);
res.json({
valid: hasAccess,
user_id: decoded.sub,
expires_at: decoded.exp
});
});
Permission Claims
Include topic permissions in the JWT:
app.post('/verify', (req, res) => {
const { jwt: token, topic } = req.body;
const decoded = jwt.verify(token, JWT_SECRET);
// Check if topic is in allowed list
const topicName = uuidToTopicName(topic);
const hasAccess = decoded.topics.includes(topicName);
res.json({
valid: hasAccess,
user_id: decoded.sub,
expires_at: decoded.exp
});
});
Topic Lifecycle
Creation
Topics are created implicitly when the first client subscribes.
Active
While at least one client is subscribed, the topic is active and receives events.
Cleanup
When the last client unsubscribes, the topic is removed from routing tables.
Distributed Topics
With multiple proxy instances, topics are synchronized:
┌─────────────┐ ┌─────────────┐
│ Proxy A │◄───────►│ Proxy B │
│ Topic: X │ NNG │ Topic: X │
│ Clients: 2 │ │ Clients: 3 │
└─────────────┘ └─────────────┘
Events published to Topic X reach all 5 clients across both proxies.
Monitoring Topics
Active Topics Count
Track the number of active topics:
Subscribers Per Topic
Monitor subscriber counts for capacity planning.
Topic Churn
High topic creation/deletion rates may indicate: - Application bugs - Reconnection storms - Client misconfiguration
Best Practices
- Use hierarchical naming:
{type}-{id}-{purpose} - Keep topic names short: Reduces memory and bandwidth
- Avoid sensitive data in names: Topic names may be logged
- Implement authorization: Control who can access which topics
- Monitor topic metrics: Detect issues early
- Document topic conventions: Help developers use topics correctly