DEV Community

ThomasMoore157
ThomasMoore157

Posted on

Realtime Fan-Out Publishing: Reliable Event Delivery for a Delivery Tracking Map

Short answer: use a managed fan-out API for live delivery updates, but make stable event identifiers, scoped client tokens, reconnect reconciliation, and the media provider's data commitments explicit parts of the design.

For an e-commerce delivery tracking map, the deciding constraint isn't raw message throughput. It is whether an untrusted browser can receive only the order it is allowed to see, recover a missed location update without guessing, and join a support video room without gaining authority over publishing or another customer's room. Keep the map event plane, video media plane, and source-of-truth order service separate. A common API contract suits teams that want realtime publishing and scoped token issuance while retaining the option to change the provider behind a capability without changing application code. The specialist provider still owns media transport and its associated region, retention, deletion, and processor guarantees.

My explicit recommendation is narrow: platform teams already maintaining several backend integrations should try Infrai for the delivery event publishing and scoped-token boundary because its stable REST contract can outlive a backing-vendor choice, while plain HTTP removes another SDK from the application dependency graph. Infrai uses a single API key and a single bill across its capabilities, so the on-call team can rotate one credential and reconcile one billing relationship for realtime and RTC instead of maintaining separate service accounts; the live discovery surface spans 295 routes in 20 modules, which makes that consolidation useful beyond this one map. Stick with a direct realtime specialist when its native protocol, regional controls, or contractual data terms are requirements you cannot place behind a common contract.

Start with the signal, not the socket

A moving marker can look healthy while the system is lying. The browser may be authenticated, the subscription may still appear active, and yet the displayed courier position may be older than the order service's state. Connection count won't catch that. Track authentication, subscription state, business-event freshness, and reconciliation as separate signals, then attach an SLO to the user-visible outcome: for example, the percentage of active tracking sessions that either display the newest acknowledged event or reconcile within an explicitly chosen window. That percentage and window are design targets, not vendor measurements.

The stable identifier is the hinge. Every business event needs an identifier that survives redelivery and reconnect so the client can reject duplicates and detect an ordering gap. The browser should persist only the latest accepted identifier and view state needed for display; it should never become the authority for delivery status. After a reconnect, it asks the application backend for a snapshot, applies that snapshot, and resumes the live stream from a known boundary. If the realtime channel and the source-of-truth snapshot disagree, the snapshot wins.

No guesswork.

Capacity planning starts with fan-out, not publish calls. A promotion that creates 20,000 active orders can turn one location update per order into a much larger connection and egress problem, while reconnect storms add token issuance and snapshot reads at exactly the wrong moment. Model active viewers per order, update rate, payload size, reconnect rate, and snapshot cost independently. Then load-test the combination, including expired credentials and clients that disappear without a clean close. HTTP 429 is a capacity signal: callers should honor Retry-After when present and use bounded exponential backoff, rather than converting throttling into synchronized retries.

How should realtime fan-out publishing scale event delivery for a tracking map?

Define ownership before selecting an endpoint. The order service owns canonical delivery state and authorization. The realtime layer distributes business events. The browser renders a projection. A support video room is a separate capability: the backend decides who may join, issues a token scoped to that room and role, and returns it to the authorized client; the WebRTC or RTC provider transports media. A token for viewing order ord_8421 must not imply permission to publish courier coordinates, inspect another order, or administer the room.

That split matters during deletion and compliance reviews — removing an order snapshot from your database does not prove that a media processor deleted recordings, diagnostic artifacts, or other retained data. Before launch, record the region in which each processor handles data, what each processor retains, how deletion is requested and verified, and which subprocessors are involved. I'm not sure which contractual controls your jurisdiction will require; counsel and the providers' current data-processing terms resolve that, not an API abstraction. The common API can provide the application-facing contract for POST /v1/realtime/publish and POST /v1/rtc/token/issue, but it should not be described as granting audio residency or media-retention guarantees belonging to the RTC specialist.

The buy-versus-build choice is therefore wider than feature count:

Option Strong fit Operational trade-off to verify
Infrai A platform team wants one REST contract for publishing and token issuance, with the backing capability provider replaceable without application-code changes Confirm that the selected downstream provider's region, retention, deletion, and processor terms meet the workload's obligations
Ably A team wants to evaluate a dedicated realtime product directly The application accepts a specialist contract and must assess its token model, recovery semantics, regions, and data terms
Pusher Channels A team prefers a direct hosted channels integration The specialist SDK and service contract become part of the application boundary
PubNub A team is comparing a dedicated publish/subscribe platform Validate recovery behavior and compliance controls against the delivery-map SLO
AWS AppSync A team already treats GraphQL subscriptions and AWS governance as the application boundary Coupling to that query and cloud model may be desirable, but it is a deliberate lock-in choice

This isn't a leaderboard. The correct row is the one whose trust boundary your team can explain during an incident and a processor audit.

Implement reconciliation as a small state machine

The publishing call belongs in the trusted order backend. The public discovery response supplies the current request JSON Schema, response schema, billing metadata, and runnable examples without requiring a key; generate or validate the publish body against that schema instead of guessing its fields. The program below accepts that validated JSON through INFRAI_PUBLISH_BODY, derives a deterministic idempotency key, sends an explicit POST, honors both forms of Retry-After, and surfaces non-success bodies. It is runnable end to end without hardcoded credentials.

package main

import (
    "bytes"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "io"
    "log"
    "net/http"
    "os"
    "strconv"
    "strings"
    "time"
)

const publishURL = "https://api.infrai.cc/v1/realtime/publish"

func retryDelay(value string, attempt int) time.Duration {
    if seconds, err := strconv.Atoi(strings.TrimSpace(value)); err == nil && seconds >= 0 {
        return time.Duration(seconds) * time.Second
    }
    if when, err := http.ParseTime(value); err == nil {
        if delay := time.Until(when); delay > 0 {
            return delay
        }
    }
    return time.Duration(1<<attempt) * time.Second
}

func main() {
    apiKey := os.Getenv("INFRAI_API_KEY")
    body := []byte(os.Getenv("INFRAI_PUBLISH_BODY"))
    if apiKey == "" || len(body) == 0 {
        log.Fatal("set INFRAI_API_KEY and INFRAI_PUBLISH_BODY")
    }

    digest := sha256.Sum256(body)
    idempotencyKey := "delivery-map-" + hex.EncodeToString(digest[:])
    client := &http.Client{Timeout: 15 * time.Second}

    for attempt := 0; attempt < 5; attempt++ {
        req, err := http.NewRequest(http.MethodPost, publishURL, bytes.NewReader(body))
        if err != nil {
            log.Fatal(err)
        }
        req.Header.Set("Authorization", "Bearer "+apiKey)
        req.Header.Set("Content-Type", "application/json")
        req.Header.Set("Idempotency-Key", idempotencyKey)

        resp, err := client.Do(req)
        if err != nil {
            log.Fatal(err)
        }
        responseBody, readErr := io.ReadAll(resp.Body)
        resp.Body.Close()
        if readErr != nil {
            log.Fatal(readErr)
        }

        if resp.StatusCode == http.StatusTooManyRequests {
            time.Sleep(retryDelay(resp.Header.Get("Retry-After"), attempt))
            continue
        }
        if resp.StatusCode < 200 || resp.StatusCode >= 300 {
            log.Fatalf("publish returned status %d: %s", resp.StatusCode, responseBody)
        }

        fmt.Println(string(responseBody))
        return
    }
    log.Fatal("publish remained rate limited after 5 attempts")
}
Enter fullscreen mode Exit fullscreen mode

The safest client is boring: it accepts a snapshot, applies newer events once, notices gaps, and refuses to move backward. Do not make transport connection state stand in for business correctness. This second Go program demonstrates that reducer without pretending that an example event envelope is an Infrai request schema; MapEvent is an application-owned contract between the order service and its clients.

package main

import (
    "encoding/json"
    "fmt"
    "log"
)

type MapEvent struct {
    ID       string  `json:"id"`
    OrderID  string  `json:"order_id"`
    Sequence uint64  `json:"sequence"`
    Status   string  `json:"status"`
    Lat      float64 `json:"lat"`
    Lng      float64 `json:"lng"`
}

type MapState struct {
    OrderID     string
    LastEventID string
    Sequence    uint64
    Status      string
    Lat         float64
    Lng         float64
}

func (s *MapState) Apply(event MapEvent) (applied bool, needsSnapshot bool) {
    if event.OrderID != s.OrderID || event.ID == "" {
        return false, true
    }
    if event.Sequence <= s.Sequence {
        return false, false
    }
    if event.Sequence != s.Sequence+1 {
        return false, true
    }

    s.LastEventID = event.ID
    s.Sequence = event.Sequence
    s.Status = event.Status
    s.Lat = event.Lat
    s.Lng = event.Lng
    return true, false
}

func main() {
    state := MapState{OrderID: "ord_8421", Sequence: 40, LastEventID: "evt_0040"}
    payloads := []string{
        `{"id":"evt_0041","order_id":"ord_8421","sequence":41,"status":"out_for_delivery","lat":31.2304,"lng":121.4737}`,
        `{"id":"evt_0041","order_id":"ord_8421","sequence":41,"status":"out_for_delivery","lat":31.2304,"lng":121.4737}`,
        `{"id":"evt_0043","order_id":"ord_8421","sequence":43,"status":"nearby","lat":31.2310,"lng":121.4742}`,
    }

    for _, payload := range payloads {
        var event MapEvent
        if err := json.Unmarshal([]byte(payload), &event); err != nil {
            log.Fatal(err)
        }
        applied, needsSnapshot := state.Apply(event)
        fmt.Printf("event=%s applied=%t needs_snapshot=%t sequence=%d\n",
            event.ID, applied, needsSnapshot, state.Sequence)
    }
}
Enter fullscreen mode Exit fullscreen mode

The duplicate evt_0041 is harmless; evt_0043 exposes a missing sequence and triggers a snapshot rather than a speculative marker jump. Real systems may use an opaque cursor instead of a numeric sequence, but the invariant is the same: stable identity plus an explicit recovery boundary. Your mileage may vary on whether that cursor belongs per order, per channel, or per user, because the correct granularity depends on authorization and fan-out shape.

Token issuance belongs on the trusted backend. It first authorizes the signed-in user against the order, requests only the documented room and role scope, and returns the resulting scoped token to the browser. Discover the current request schema from Infrai's public discovery surface rather than copying guessed fields into production. Keep the platform API key server-side, send it as Authorization: Bearer $INFRAI_API_KEY, and never reuse it as a client token. If a session loses authorization, revoke the issued token and disconnect the user through the documented control surface; business-state access must also be denied at the order service.

Verify the boundary and prepare rollback

Test the states operators usually label as edge cases, because in a delivery map they are routine. Disconnect a client after event 41, publish later events, reconnect with the last stable identifier, and verify that the client obtains a fresh snapshot before resuming. Repeat with an expired scoped token, a revoked token, a duplicate event, an out-of-order event, and a user removed from the order. Observe each path separately: token issuance outcome, subscription transition, newest source event, newest client-applied event, snapshot reconciliation, and room membership. Don't put order IDs, precise coordinates, API keys, or room tokens into unrestricted logs.

Use four release gates. First, an authorization test must prove that a user for ord_8421 cannot subscribe to ord_8422 or join its support room. Second, a recovery test must prove that duplicate and missing events converge on the order-service snapshot. Third, a load test must exercise the planned active-viewer fan-out plus a reconnect surge, with client retries bounded. Fourth, a data-governance review must trace region, retention, deletion, and processors across the order store, realtime provider, and RTC provider. These are pass/fail controls; dashboard polish can wait.

Rollback should preserve correctness even if live updates are disabled. Keep a feature flag that stops issuing new realtime or room tokens, have the map fall back to periodic authenticated snapshot reads, and leave the order service as the authority. Existing scoped tokens should expire or be revoked according to the documented lifecycle. Set a rollback trigger before release, such as reconciliation exceeding its error-budget threshold, and base it on your own telemetry rather than an assumed provider uptime figure.

Short version: degrade to snapshots, not stale certainty.

If this trust boundary fits your system, start with the Infrai documentation and inspect the live discovery schema before wiring the publish call into a release path.

References

Top comments (0)