Registry & Envelope

Registry Interface

The Registry handles serialization and deserialization of events:

type Registry interface {
    Register(name string, factory Factory, version int)
    Decode(ctx context.Context, data []byte) (context.Context, Event, error)
    Encode(ctx context.Context, evt Event) ([]byte, error)
}

Where Factory creates a new empty event instance:

type Factory func() Event

Envelope

Every serialized event is wrapped in an Envelope:

type Envelope struct {
    Name      string          `json:"name"`
    Version   int             `json:"version"`
    Timestamp time.Time       `json:"ts"`
    TraceID   string          `json:"trace_id,omitempty"`
    SpanID    string          `json:"span_id,omitempty"`
    Payload   json.RawMessage `json:"payload"`
}

Example JSON:

{
  "name": "user.created",
  "version": 2,
  "ts": "2026-02-05T12:00:00Z",
  "payload": {"user_id": "123", "email": "john@example.com"},
  "trace_id": "abc123...",
  "span_id": "def456..."
}

The envelope enables:

  • Versioned schema evolution via upcasters
  • Trace correlation across transport boundaries
  • Safe replay and DLQ handling

Upcaster Interface

Upcasters transform older event versions to newer ones:

type Upcaster interface {
    EventName() string
    FromVersion() int
    ToVersion() int
    Upcast(ctx context.Context, raw json.RawMessage) (json.RawMessage, error)
}

Upcasters are pure functions and deterministic. They are chained automatically by the registry: V1 → V2 → V3.

See Schema Versioning for details.


Back to top

Copyright © 2025 Isaque de Souza Barbosa. Distributed under the MIT License.