TIDE • Troubleshoot

Server-Side Rendering & Edge Streaming

Edge streaming patterns, cache-control headers, and Hono microservice integration.

Server Patterns & Edge Streaming

Backend caching conventions, HTTP response headers, and WebSocket broadcast patterns optimized for Tide clients.

ETag / 304 Handling in Cloudflare Workers and Hono

Responding with 304 Not Modified eliminates bandwidth consumption and JSON deserialization overhead on the client.

TypeScript
import { Hono } from 'hono';

const app = new Hono();

app.get('/api/dashboard/stats', async (c) => {
  const clientEtag = c.req.header('If-None-Match');
  const currentVersion = await getStatsVersion();
  const etag = `W/"stats-${currentVersion}"`;

  if (clientEtag === etag) {
    return c.body(null, 304);
  }

  const stats = await getStatsPayload();
  c.header('ETag', etag);
  c.header('Cache-Control', 'public, max-age=10, s-maxage=30');
  return c.json(stats);
});

export default app;

Pre-Computed Atomic Cache in Go Microservices

Marshal JSON once in a background worker goroutine and serve raw bytes directly with zero runtime serialization per request:

Go
package main

import (
	"crypto/sha256"
	"fmt"
	"sync/atomic"
	"github.com/gofiber/fiber/v2"
)

type CachePayload struct {
	Bytes []byte
	ETag  string
}

var globalCache atomic.Pointer[CachePayload]

func UpdateCacheWorker(data any) {
	bytes, _ := json.Marshal(data)
	etag := fmt.Sprintf("\"%x\"", sha256.Sum256(bytes))
	globalCache.Store(&CachePayload{Bytes: bytes, ETag: etag})
}

func GetStatsHandler(c *fiber.Ctx) error {
	cached := globalCache.Load()
	if cached == nil {
		return c.SendStatus(fiber.StatusServiceUnavailable)
	}

	if c.Get("If-None-Match") == cached.ETag {
		return c.SendStatus(fiber.StatusNotModified)
	}

	c.Set("ETag", cached.ETag)
	c.Set("Content-Type", "application/json")
	return c.Send(cached.Bytes)
}

Enriched WebSocket Broadcasting

Always enrich WebSocket broadcast events with the complete object representation rather than partial event diffs.

TypeScript
// Good: Broadcast contains full entity; Tide updates signal without HTTP fallback
server.broadcast({
  type: 'agent_status_changed',
  data: {
    agent: {
      id: 'agent_01',
      status: 'active',
      activeTask: 'Compiling seeds',
      updatedAt: Date.now(),
    },
  },
});

// Bad: Sparse message forces Tide to fallback to HTTP polling
server.broadcast({
  type: 'agent_status_changed',
  agentId: 'agent_01', // Missing details
});