Concepts

Events

How Redelay events work — definitions, publishing, consuming, and schema validation.

Events are the first-class citizens in Redelay. Every side effect — a user signing up, a domain dropping, an order placed — is modelled as an event.

Event message structure

Every event follows this envelope (flat field layout):

json
{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "correlation_id": "7f3b1c2e-...",
  "timestamp": "2026-04-07T09:00:00.000Z",
  "entity_type": "order",
  "entity_id": "order-123",
  "action": "created",
  "actor_type": "user",
  "actor_id": "user-456",
  "payload": "{\"order_id\":\"order-123\",\"total\":99.00}"
}

The entity_id is used as the Kafka partition key — all events for the same entity are ordered.

Defining events

goGo
import "github.com/redelay/go-events/typed"

type OrderCreatedPayload struct {
    OrderID string  `json:"order_id"`
    Total   float64 `json:"total"`
}

var OrderCreatedEvent = typed.EventDefinition[OrderCreatedPayload]{
    Name:       "order.created",
    EntityType: "order",
    Action:     "created",
    Topic:      "order.created",
}

Publishing events

goGo
// deps.EventBus (modules.ModuleDeps) is injected at bootstrap — auto-wired by
// blank-importing github.com/redelay/go-events/module, or via app.WithEventBus(bus)
msg, _ := OrderCreatedEvent.NewMessage(
    order.ID,
    typed.Actor{Type: typed.ActorTypeUser, ID: userID},
    OrderCreatedPayload{OrderID: order.ID, Total: order.Total},
)
deps.EventBus.Publish(ctx, msg)

Consuming events

goGo
bus.Register(&modules.ConsumerRegistration{
    Topic:   "order.created",
    GroupID: "notifications",
    Handler: func(ctx context.Context, msg *modules.EventMessage) error {
        var p OrderCreatedPayload
        json.Unmarshal(msg.Payload, &p)
        log.Printf("order: %s total: %.2f", p.OrderID, p.Total)
        return nil
    },
})
bus.Start(ctx)

Handler routing is by (entity_type, action) pair. Multiple handlers for the same pair are chained via EventMultiplexer.

Schema validation

Both services load the AsyncAPI schema from the backend on startup and validate every received event payload against it.

  • Go: SchemaRegistry.ValidatePayload(eventName, payload) — retries with backoff on startup
  • Python (coming soon): Generated at /asyncapi/v1/schema.json by py-events

Correlation IDs

Always propagate correlation_id from an incoming event to any events you publish in response. This maintains trace chains across the entire pipeline.