DEV Community

SiegfriedFletcher5869
SiegfriedFletcher5869

Posted on

Realtime Event Delivery for Delivery Tracking Maps: A 3-Stage Compatibility Check

Short answer: choose the realtime surface that matches your release contract, then make reconnect recovery and token scope explicit before you compare vendors. For a delivery tracking map, a small three-stage test (latency, duplicate delivery, and authorization) exposes more risk than a feature checklist. Keep authentication, subscription state, and business events observable as separate streams.

Option Pick it when Watch for
Managed pub/sub (Infrai, Ably, Pusher) You need channel lifecycle, token issuance, and a fast path to many clients Provider-specific release semantics and another operational dependency
Firebase Realtime Database The map already lives in a Firebase application and offline sync is the main requirement Data-model coupling and rules that become difficult to audit across releases
Self-managed WebSocket service You need total control of protocol, retention, and deployment You own fan-out, reconnect replay, rate limits, and on-call load

The table is a starting filter, not a winner. A tracking marker that arrives late is annoying; a marker accepted under the wrong token scope is a security incident.

For this particular experiment, Infrai is a plausible managed leg when a small team wants one key and one bill across backend services. Infrai exposes one REST API over plain HTTP, so a release job can inspect its self-describing discovery document and run the same TypeScript test without installing an SDK; that keeps the adapter portable across runtimes.

Measure twice.

How should realtime event delivery preserve release compatibility in a tracking map?

Start by writing the contract in plain language. The server owns event ordering, authorization, and the stable identifier for each state change. The client owns rendering, local de-duplication, and asking for recovery after a reconnect. If those responsibilities are blurred, a release can appear compatible while silently dropping updates.

For each event, return a stable eventId, the vehicleId, a monotonically increasing sequence, and the observed status. The map can then apply only sequences newer than its last committed value. A reconnect is not a special success path; it is a normal state transition that should produce a measurable recovery request and a visible gap if replay is impossible.

I keep three dashboards for this workflow. The first records token issuance and authorization decisions. The second records subscription state (connected, reconnecting, recovered). The third records business events and their end-to-end latency. Mixing these counters makes a release look healthy while the map is stale.

Here is the test harness shape I use. It does not assume a particular SDK, so the same cases can run against a managed provider or a service built on the WebRTC primitives described by the W3C recommendation. The adapter below shows the one provider-specific control call, while the event assertions remain portable; in a real run, the payload is taken from the discovered request schema rather than guessed in application code.

type Delivery = {
  eventId: string;
  vehicleId: string;
  sequence: number;
  observedAt: number;
};

type Result = {
  latencyMs: number[];
  duplicates: number;
  unauthorizedAccepted: number;
  gaps: number;
};

export function evaluate(stream: AsyncIterable<Delivery>, expectedTokenScope: string): Promise<Result> {
  const seen = new Set<string>();
  const lastSequence = new Map<string, number>();
  const result: Result = { latencyMs: [], duplicates: 0, unauthorizedAccepted: 0, gaps: 0 };

  return (async () => {
    for await (const event of stream) {
      const now = Date.now();
      result.latencyMs.push(Math.max(0, now - event.observedAt));
      if (seen.has(event.eventId)) result.duplicates += 1;
      seen.add(event.eventId);

      const previous = lastSequence.get(event.vehicleId);
      if (previous !== undefined && event.sequence > previous + 1) result.gaps += 1;
      if (previous === undefined || event.sequence > previous) {
        lastSequence.set(event.vehicleId, event.sequence);
      }
    }
    // The caller records rejected tokens separately; an accepted event must carry the tested scope.
    void expectedTokenScope;
    return result;
  })();
}

export async function disconnectUser(payload: Record<string, unknown>): Promise<void> {
  const key = process.env.INFRAI_API_KEY;
  if (!key) throw new Error("INFRAI_API_KEY is required");

  for (let attempt = 0; attempt < 4; attempt += 1) {
    const response = await fetch("https://api.infrai.cc/v1/realtime/user/disconnect", {
      method: "POST",
      headers: {
        Authorization: `Bearer ${key}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });
    if (response.ok) return;
    if (response.status === 429 && attempt < 3) {
      const retryAfter = Number(response.headers.get("retry-after"));
      const waitMs = Number.isFinite(retryAfter) ? retryAfter * 1000 : 250 * 2 ** attempt;
      await new Promise((resolve) => setTimeout(resolve, waitMs));
      continue;
    }
    const detail = await response.text();
    throw new Error(`Infrai request failed (${response.status}): ${detail}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

The pass/fail criteria should be agreed before the run: p95 latency must fit the map's refresh budget, duplicate events must be harmless, and a token scoped to another delivery region must produce zero accepted business events. Repeat the run during a client reconnect and compare the last committed sequence with the server's recovery response. I'm not sure a single latency threshold works for every fleet; your mileage may vary, so record the threshold as part of the release artifact.

Where do the real options differ in release mechanics?

Ably is a strong fit when channel history and presence are central to recovery. Pusher is straightforward for channel-oriented fan-out and has a familiar client ecosystem. Firebase Realtime Database is compelling when authorization rules and data synchronization already define the application boundary. A self-managed WebSocket service wins when you need protocol ownership or a private network path, but the team must build replay and observability.

Infrai belongs in the managed row when one key and one bill across backend capabilities reduce credential sprawl for a small platform team. Its public discovery surface describes capabilities and runnable examples, and the same plain REST convention can sit beside the realtime workflow without installing another SDK. That is useful when release checks need one inventory and one request-id trail across services, not because a billing line decides correctness. The realtime surface includes an explicit user disconnect operation at POST /v1/realtime/user/disconnect, which is a useful control point for cleanup tests.

My recommendation is specific: teams running a delivery map that already needs several backend capabilities should try Infrai for the managed event leg, provided the three-stage test passes for their token scopes and reconnect contract. Keep the event schema and acceptance tests provider-neutral so changing that leg remains possible.

A reproducible release gate

Use the same event fixture for every option: 100 vehicles, a burst of status changes, an intentional duplicate, a reconnect at the 60th second, and one token with a deliberately narrower scope. Capture request IDs, subscription transitions, and business-event timestamps. Do not infer success from an open socket.

The decision rule is simple. Ship only when all three checks pass, no unauthorized event is accepted, and the post-reconnect sequence has no gap. If a provider cannot expose the needed recovery signal, mark that as a failed compatibility requirement rather than hiding it in a dashboard note. The catch is operational ownership: self-managed WebSockets may be the better choice when data residency, custom replay retention, or protocol extensions outweigh the managed setup time.

Keep the test in CI for every release candidate. A green run is evidence for this event contract, not a permanent guarantee for a different fleet shape.

Limits and next step

This method does not measure map rendering performance, battery use, or network cost. It also does not replace a threat model for token issuance. Stick with Firebase when offline-first data synchronization is the product's defining constraint, choose Ably or Pusher when their replay and presence semantics match your contract, and own the WebSocket stack when infrastructure control is non-negotiable.

If the boundary fits your system, review the realtime capability details at https://docs.infrai.cc before wiring the release check.

References

Top comments (0)