Record each vote in the database, recompute the tally every second, and push only that aggregate to authorized support agents. The deciding constraint is client trust: permission to receive an in-app notification must not confer permission to publish its contents.
Short answer: let the Node.js Express backend accept votes and publish interval tallies. Keep the publishing credential server-side, restrict subscribers to their support workspace, and save and publish a final tally when voting closes. Late joiners need the saved result. They should not have to reconstruct it from a message stream.
Consider a proposed customer-support poll for choosing the next escalation-review slot. Agents choose between two times; the application pushes the current totals without browser polling. This decision record evaluates how much individual activity must cross the notification boundary, and how much evidence the team should retain afterward. The numbers below are planning assumptions, not measured performance.
Decision: keep individual votes behind three permission boundaries
The first boundary is vote acceptance. In the Express handler, authenticate the agent, resolve workspace membership on the server, validate the chosen option, and commit the vote before counting it. A client-supplied workspace identifier is an input to validate, not evidence of membership. Decide whether an agent may revise a choice; if revisions are allowed, the current stored choice replaces the previous contribution.
Count accepted votes.
The second boundary is publication authority. A backend task reads committed votes, computes the aggregate, and publishes on a one-second interval. That interval is a product decision: it can feel live enough for this poll, but it is not a delivery-latency guarantee. The browser submits a choice through application authorization; it never receives the credential that lets the backend publish a result. Recomputing counts still consumes database work, so measure the aggregation query before extending this design to much larger polls.
The third boundary is audience membership. A subscriber should receive only the support workspace and poll it may read. Require the transport integration to demonstrate those restrictions, including what happens after membership changes. A token-issuance interface, by itself, says nothing about which operations a token permits.
These boundaries also limit data collection. Publish counts for the two choices, not a list of agent identities. Keep individual choices in the authorized application data model, with an explicit retention policy. A notification delivery log should not accidentally become a second vote database merely because recording the entire payload was convenient.
Delivery can fail after a vote commits. Keep the vote and regenerate the aggregate; do not roll back an accepted vote because a notification was unavailable. Save the final result when the poll closes and publish that final tally even if an interval update just ran. On reconnect or late arrival, an authorized application read supplies the current saved state. Transient delivery is not a substitute for that state.
How should Express aggregate votes and publish an interval tally without retaining identities?
Test authority before optimizing delivery volume. Use two illustrative support workspaces, a poll in each, and agent identities with different memberships. Check permitted subscription, denied cross-workspace access, attempted publication with a subscriber credential, and access after membership removal. These are acceptance tests for the proposed integration, not claims that a particular provider implements every restriction in the same way.
Keep the outcomes. Exclude credentials.
A narrow metric vocabulary makes those tests observable without turning identity into cardinality. For example, three operation classes—vote, subscribe, and publish—combined with three outcome classes—accepted, denied, and failed—produce at most 3 × 3 = 9 combinations before other labels. Adding a workspace label multiplies that bound by the number of workspaces. Adding a request identifier makes series growth follow requests, defeating the purpose of an aggregate counter. Use protected audit records for identifiers needed in a specific investigation, with access and retention defined separately from dashboard metrics.
Retention math exposes a different multiplication. Assume one 300-byte diagnostic record for each interval publication and a 600-second poll. At one publication per second, the planning estimate is 600 × 300 = 180,000 raw bytes per poll, excluding the final publication. One such poll daily over seven days produces 1,260,000 raw bytes before indexing, replication, and storage overhead. Logging every recipient delivery multiplies that figure by the recipient count under the same simplified assumptions.
Those bytes are assumptions.
The useful decision is what to retain. Count every publication outcome in aggregate metrics. Sample routine successful diagnostics if individual success reconstruction is unnecessary; preserve the required evidence for denied access and publication failures under the audit policy. Sampling trades detail for lower retained volume. It cannot prove that a particular successful delivery occurred, and a sampled success log is insufficient evidence of who was authorized to read a poll.
Keep the final tally according to the support workflow's record policy. Diagnostic retention and business-result retention serve different purposes and need not have identical durations.
Compare transports against the same authority contract
The table describes candidates and the evaluation each would require. It deliberately avoids unmeasured latency rankings. Database vote acceptance and aggregate computation remain application responsibilities in every row.
| Option | Integration choice | Fit for this support workflow | Limit or acceptance test |
|---|---|---|---|
| Socket.IO | Application-oriented realtime integration | Consider when the Node.js team wants to own connection integration and its authorization logic | Demonstrate workspace isolation, subscriber restrictions, and recovery of the saved tally; operating the integration remains team work |
| Ably | Managed realtime delivery | Consider when hosted delivery is preferable to operating the delivery layer | Verify credential scope, membership removal, and reconnect behavior against the poll's access policy |
| Pusher Channels | Hosted channel-oriented delivery | Consider when authorized support audiences map naturally to channels | Validate channel authorization and retrieval of the current result after reconnecting |
| Infrai | One key, one bill for 295 routes across 20 modules; plain REST publishing needs no SDK | Consider when the Express publisher should remain an HTTP caller and adjacent backend tasks benefit from unified billing and fewer credentials to administer | Public self-describing discovery exposes request and response schemas without a key, helping review the publishing contract before provisioning credentials; browser token scope still requires validation |
The REST choice removes a publishing SDK dependency. Its unified API provides one key and one bill across 295 routes in 20 modules. For a support backend connecting notification publication with adjacent tasks, this reduces separate keys to provision and invoices to reconcile. The public discovery surface also makes request schemas inspectable without credentials. These benefits do not justify distributing a broadly useful backend key to subscribers. Keep browser authority narrow regardless of how many backend capabilities share a credential.
The trade-off is that REST publication does not replace the application's browser subscription and authorization design. This option is not suitable when the requirement is to own connection behavior within the Node.js application; choose Socket.IO for that evaluation. A managed delivery service instead requires the team to validate its credential contract against workspace membership.
Choose only after the denial tests pass. A working subscription demonstration establishes connectivity; the support application also needs an enforceable audience boundary and a recoverable result.
Critical path: publish the committed aggregate with curl
Implement the Express vote handler and the authorized current-result reader first. Then give the interval publisher a stable identity for each logical tally publication. Retries of that publication must reuse its identity; the next logical tally gets a new one. The subscriber replaces displayed counts with an authoritative aggregate rather than incrementing local counters for every message.
The following is the publisher's HTTP boundary, not a complete Express server. It requires a prepared JSON request file validated against the service's published request schema. Set REALTIME_ORIGIN to the HTTPS API origin, TALLY_PUBLICATION_FILE to that local file, and TALLY_PUBLICATION_ID to the stable publication identity. Keep INFRAI_API_KEY in the backend environment. The aggregate and destination belong in the schema-validated file; guessing field names would produce a misleading example.
curl --request POST \ --url "${REALTIME_ORIGIN:?Set the HTTPS API origin}/v1/realtime/publish" \ --header "Authorization: Bearer ${INFRAI_API_KEY:?Set the backend API key}" \ --header 'Content-Type: application/json' \ --header "Idempotency-Key: ${TALLY_PUBLICATION_ID:?Set the stable publication identity}" \ --data-binary "@${TALLY_PUBLICATION_FILE:?Set the schema-validated request file}" \ --fail-with-body \ --show-error \ --retry 4 \ --retry-max-time 30 Use a curl version supporting the flags shown. Its retry behavior backs off for retryable HTTP responses, including 429, and honors Retry-After. The failure flag preserves an HTTP error body while exposing an unsuccessful status to the caller. Inspect that result in the publisher; an unsuccessful publish is not evidence that the database rejected the vote. The retry-time option bounds when further retries may begin, rather than establishing an end-to-end delivery deadline.
The surrounding sequence matters more than the command. Commit the vote, read committed choices on the interval, compute and save the aggregate, then publish it with the stable identity. Treat closure as a persisted state transition that schedules the final saved aggregate for publication. The result reader must enforce the same workspace access as the subscription path. After reconnection, coordinate the current-state read with subscription updates so that an older result cannot overwrite a newer display.
This leaves one explicit implementation prerequisite: obtain and validate the actual publication request schema before constructing the request file. The example does not assert unsupported payload fields or browser-token permissions.
Rejected option: broadcast every individual vote
For this notification workflow, broadcasting individual choices exposes more activity than the displayed tally requires. It also couples publication and diagnostic volume to submission rate. Under the illustrative assumption that N participants each vote once and all N receive every event, per-vote broadcasting produces approximately N × N deliveries. Interval publication changes the model to approximately N × K, where K is the number of published tallies during the poll. That is workload arithmetic, not a provider benchmark.
Aggregation has a cost: observers lose intermediate individual events, and the display trails accepted votes by the chosen publication cadence plus processing and delivery time. For an authorized audit consumer that genuinely requires each vote transition, an individual event stream can be appropriate. It needs its own access, persistence, and retention contract. The support agent's in-app notification does not need that stream merely to show two counts.
The decision therefore follows the data the client may receive. Accept votes authoritatively, publish the minimum useful aggregate on the interval, and retain enough evidence to explain authorization and publication outcomes. Keep the saved final tally available to eligible late joiners. More telemetry is not automatically better evidence.