Push Event To User
Overview
Push Event To User sends real-time events from flows to users' web browsers through channel-based messaging. Use this stage to send live updates, notifications, status updates, progress indicators, and trigger UI changes from backend flows.
Example: Notify users only when their order is completed
This flow loops over a list of orders, uses Route Flow to check if each order's status is completed, and only calls Push Event To User for orders that pass that check. The stage sends a message to that order's unique channel. Pass only confirms the publish succeeded, not that the user received it.
Where to find it: Actions in the stage library.
Configuration
Required Fields
| Field | Description | Example |
|---|---|---|
| Channel | Channel name to publish events to (must match front-end subscription) | userNotifications, session_{{sessionId}}, user_{{userId}} |
| Values | Key-value pairs to send in event message (at least one required) | Name: message, Value: Order processed successfully |
Channel Naming
Important: Channel names are automatically prefixed with your operator's public key to prevent collisions:
- You configure:
userNotifications - Actual channel:
{publicKey}_userNotifications - Front-end must subscribe using full prefixed name
Security Note: Channel names are not encrypted. Use hard-to-guess names (UUIDs, session IDs) for sensitive channels.
Value Fields
Each key-value pair includes:
- Name: Key name in JSON message (e.g.,
message,status,data) - Value: Data to send (supports strings, JSON objects, JSON arrays, variables)
JSON Auto-Detection:
- Values starting with
{(not{{) parsed as JSON objects - Values starting with
[parsed as JSON arrays - Double braces
{{escape JSON parsing (treated as string) - All other values treated as strings
Using functions in these fields: Any value field above accepts @ functions, for example @NowSecond for the current time or @calc(...) for a calculation. See Flows Functions for the full list.
Exit Points
| Exit | When |
|---|---|
| Pass | The message was published successfully. This is the normal outcome whether or not anyone is listening, the stage does not check how many subscribers received it, so zero subscribers still passes |
| Fail | The publish itself failed (the messaging service was unreachable). It is retried once first; if it still fails, the stage takes Fail and the error is logged |
Important: there is no Error exit, and the count of subscribers has no effect on routing. Two things to know:
- Zero subscribers is still a Pass. The message is sent in real time and simply not delivered to anyone, but the stage passes. You cannot use Pass/Fail to tell whether a user was online.
- Invalid JSON in a value aborts the whole run. If a value is meant to be a JSON object or array but is malformed, the stage cannot build the message and the entire flow run stops here (it does not take Fail). Validate any JSON value before this stage.
How It Works
When executed, the stage:
- Prefixes channel - Adds operator public key to channel name for isolation
- Builds JSON message - Creates message with channel field and all configured key-value pairs
- Detects value types - Parses JSON objects/arrays or treats as strings (malformed JSON here aborts the run)
- Publishes the message - Broadcasts it in real time to anyone subscribed to the channel
- Routes to Pass - Passes once the publish succeeds, regardless of how many subscribers received it (a publish error is retried once, then takes Fail)
Key behavior: Messages are real-time only (not persisted). If no subscribers are connected, the message is simply not delivered, but the stage still passes. Requires the FlowsJS library on the client side.
Message Format
Published JSON always includes:
channel: Full channel name (with operator prefix)- All configured key-value pairs
- Nested JSON objects and arrays preserved
Example Message:
{ "channel": "abc123_userNotifications", "message": "Your order has been processed", "orderId": "12345", "status": "completed", "details": { "total": 99.99, "items": 3 } }
Common Use Cases
1. Simple Notification
Notify user their order was processed.
Configuration:
- Channel:
user_{{userId}} - Values:
- Name:
message, Value:Your order has been processed - Name:
orderId, Value:{{orderId}}
- Name:
Result: The stage passes once the message is sent, whether or not the user is currently connected.
2. JSON Object Payload
Send complex order details to dashboard.
Configuration:
- Channel:
dashboard_updates - Values:
- Name:
type, Value:order_complete - Name:
order, Value:{"id":"{{orderId}}","total":{{total}},"items":{{itemCount}}}
- Name:
Result: Message sent with nested JSON object. Dashboard widgets receive update.
3. Broadcast to Multiple Users
Send system announcement to all connected users.
Configuration:
- Channel:
system_announcements - Values:
- Name:
message, Value:System maintenance in 10 minutes - Name:
severity, Value:warning
- Name:
Result: All clients subscribed to the channel receive the message. The stage passes once it is sent, even if no client is connected.
4. Progress Update
Send progress updates during long flow.
Configuration:
- Channel:
job_{{jobId}} - Values:
- Name:
progress, Value:{{currentStep}} - Name:
total, Value:{{totalSteps}} - Name:
message, Value:Processing step {{currentStep}} of {{totalSteps}}
- Name:
Result: Client monitoring job receives progress update. Can be called multiple times in loop.
5. Session-Specific Channel
Send message to specific user session.
Configuration:
- Channel:
session_{{sessionId}} - Values:
- Name:
action, Value:refresh_data - Name:
timestamp, Value:{{now}}
- Name:
Result: Only specific session receives message. Other users not affected.
Key Behaviors
| Feature | Behavior |
|---|---|
| Real-Time Only | ✓ Messages not persisted - delivered only to active subscribers |
| Auto-Prefix | ✓ Channel names automatically prefixed with operator public key |
| JSON Detection | ✓ Values starting with { or [ parsed as JSON ({{ escapes parsing) |
| No Persistence | ✓ If no subscribers, the message is lost, but the stage still passes |
| Broadcast | ✓ All subscribers on channel receive same message |
| Routing | Pass on a successful publish (any subscriber count, including zero); Fail only if the publish fails (retried once first); malformed JSON aborts the run |
| No Error Exit | ✓ Only Pass and Fail exits |
Best Practices
- ✓ Use specific channel names:
user_{{userId}}orsession_{{sessionId}} - ✓ Include message type: Add
typeoractionfield for client routing - ✓ Keep messages small: Limit to essential data (recommend <1MB)
- ✓ Use UUIDs for privacy: Avoid predictable channel names for sensitive data
- ✓ Validate JSON before sending: Test JSON payloads to avoid runtime errors
- ✓ Handle Fail exit gracefully: it fires only if the message could not be published (messaging service unreachable), use it to log or fall back
- ✓ Don't send secrets: Channel names and messages are not encrypted
- ✓ Test with FlowsJS: Ensure front-end properly configured before production
- ✓ Add timestamps: Include timestamp for client-side ordering
- ✓ Don't use Pass/Fail to detect online vs offline users: it passes either way. To know if a user acted, have the client send an event back
Common Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
| Forgetting operator prefix | Front-end doesn't receive messages | Ensure FlowsJS uses {publicKey}_channelName |
| Sending sensitive data | Security risk | Never send passwords or API keys - use tokens or references |
| Expecting message persistence | Offline users don't receive messages | Use database or queue for guaranteed delivery |
| Assuming Fail means the user is offline | Fallback logic triggers on the wrong condition | Fail fires only if the publish failed; a message to an offline user still passes. Don't route offline handling off Fail |
| Invalid JSON syntax in a value | The whole flow run stops at this stage | Validate any JSON value before this stage; malformed JSON aborts the run (it does not take Fail) |
| Hardcoded channel names | All users receive same messages | Use variables: user_{{userId}} or session_{{sessionId}} |
| Large message payloads | Slow performance | Send notification only, client fetches details via API |
Troubleshooting
| Issue | Common Cause | Fix |
|---|---|---|
| Stage routes to Fail | The messaging service could not be reached (not a subscriber issue, zero subscribers still passes) | Check the messaging service health; the publish is retried once before Fail |
| Front-end doesn't receive messages (stage still passes) | Channel name mismatch, or no client subscribed | Check the channel name includes the operator prefix and the client is subscribed; the stage passes regardless of delivery |
| Flow run stops at this stage | A value meant to be JSON is malformed | Validate the JSON value before this stage; bad JSON aborts the run |
| Offline users missing messages | Real-time messaging is not stored for later delivery | Use database or queue for guaranteed delivery to offline users |
| Message not targeted to specific user | Using shared channel name | Use unique channels per user/session: user_{{userId}} |
Do's and Don'ts
Do:
- ✓ Use dynamic channel names with user/session IDs
- ✓ Include message type field for client routing
- ✓ Handle Fail exit for offline users
- ✓ Keep messages small and focused
- ✓ Test with FlowsJS before production
Don't:
- ✗ Send passwords or sensitive secrets
- ✗ Expect messages to be stored for offline users
- ✗ Use predictable channel names for sensitive data
- ✗ Send large payloads (keep under 1MB)
- ✗ Forget operator prefix on front-end subscriptions
- ✗ Rely on this for critical must-deliver notifications
Edge Cases
- No subscribers connected: the message is published but delivered to no one, and the stage still passes (the message is lost)
- Multiple subscribers on same channel: all receive the same message; the stage passes regardless of the count
- Invalid JSON in a value: the stage cannot build the message and the whole flow run aborts here (it does not take Fail)
- Double braces {{:
{{value}}treated as string (escapes JSON parsing) - Messaging service unreachable: the publish is retried once (two attempts total); if it still fails, the stage takes Fail and the error is logged
- Channel name collision: Prevented by operator public key prefix (different operators isolated)
Related Stages
- Route Flow: Check user status before deciding to push or queue
- Loop: Send multiple push events to different users/sessions
- Change Data: Prepare message data before pushing