Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Key Concepts

These are the core terms used throughout Aviso’s documentation and API. Read this page before Getting Started to make the commands easier to follow.


Event Type

An event type is a named category of notification, for example extreme_event, sensor_alert, or data_ready.

Every request to Aviso (notify, watch, or replay) targets exactly one event type. The server uses the event type to:

  • look up the matching schema (validation rules, required fields, topic ordering),
  • route messages to the correct storage stream,
  • apply the correct retention and storage policy.
{ "event_type": "extreme_event", ... }

When a notification_schema is configured, Aviso is strict by default: any event_type that is not in the schema is rejected with 400 UNKNOWN_EVENT_TYPE on /api/v1/notification, /api/v1/watch, and /api/v1/replay. The error body lists the configured event types so clients can self-correct.

When notification_schema is empty or absent (no schema declared at all), Aviso falls back to generic behavior: any event type is accepted, fields are treated as-is, and the topic is built from sorted keys. This mode is intended for local development and quick experiments.

Operators may flip the behavior with notification_schema_strict:

notification_schemanotification_schema_strictEffective behavior
non-emptyNone (unset)strict: unknown event types return 400
empty / absentNone (unset)permissive generic fallback
anyfalsepermissive generic fallback (legacy mode; a startup warning is emitted when the schema is non-empty)
anytruestrict: unknown event types return 400; with no schema this is deny-all

Independent of the strict-mode knob, the event_type value that ends up on Prometheus labels and tracing span fields is always bounded: requests whose event_type is not in the configured schema have their observability label collapsed to the literal "generic". In strict mode this collapsing is rarely exercised because unknown event_types are already rejected upstream with 400 UNKNOWN_EVENT_TYPE; in permissive (legacy generic-fallback) mode it is the main mechanism preventing unbounded label cardinality from user-controlled input.


Identifier

An identifier is a set of key-value pairs that describe what a notification is about. Think of it as structured metadata that uniquely (or approximately) locates a piece of data.

{
  "identifier": {
    "region":   "north",
    "run_time": "1200",
    "severity": "4",
    "anomaly":  "42.5"
  }
}

Identifiers serve two purposes depending on the operation:

OperationRole of identifier
notifyDeclares the metadata of the notification being published
watchActs as a filter for which notifications to receive
replayActs as a filter for which historical notifications to retrieve

In watch and replay, identifier values can be constraint objects instead of scalars (e.g. {"gte": 5}) for numeric and enum fields. See Streaming Semantics.


Topic

A topic is the internal routing key Aviso builds from an identifier. You rarely construct topics manually; Aviso builds them for you.

Topics are dot-separated strings, for example:

extreme_event.north.1200.4.42%2E5

Each token corresponds to one identifier field, in the order defined by key_order in the schema. The %2E is the dot in 42.5, percent-encoded so it doesn’t conflict with the topic separator. Reserved characters (., *, >, %) in field values are percent-encoded before writing to the backend so they do not break routing. See Topic Encoding.


Schema

A schema configures how Aviso handles a specific event type. Schemas are defined in configuration/config.yaml under notification_schema.

A schema controls:

  • topic.base: the stream/prefix for this event type (e.g. diss, mars)
  • topic.key_order: the order of identifier fields in the topic string
  • identifier.*: validation rules per field (type, required, allowed values, ranges)
  • payload.required: whether a payload is mandatory on notify
  • storage_policy: per-stream retention, size limits, compression (JetStream only)

Example:

notification_schema:
  extreme_event:
    topic:
      base: "extreme_event"
      key_order: ["region", "run_time", "severity", "anomaly", "polygon"]
    identifier:
      region:
        description: "Geographic region label."
        type: EnumHandler
        values: ["north", "south", "east", "west"]
        required: true
      run_time:
        type: TimeHandler
        required: true
      severity:
        description: "Severity level from 1 to 7."
        type: IntHandler
        range: [1, 7]
        required: true
      anomaly:
        type: FloatHandler
        range: [0.0, 100.0]
        required: false
      polygon:
        type: PolygonHandler
        required: false
    payload:
      required: false

Every key listed in key_order must have a corresponding entry in identifier. For notify, every identifier key declared in the schema must be present in the request and every value must pass the handler’s validation (an empty string, an out-of-range integer, an unparseable date, and so on are all rejected). The required flag has no effect on notify; it only changes the behavior of watch and replay. There, a missing key marked required: true returns 400, while a missing key marked required: false is treated as a wildcard. The flag never relaxes value validation; only the presence rules.


Payload

A payload is arbitrary JSON attached to a notification. Aviso treats it as opaque; it stores and replays the value exactly as sent.

Valid payload types: object, array, string, number, boolean, or null.

{ "payload": { "path": "/data/grib2/file.grib2", "size": 1048576 } }

Whether payload is required or optional is controlled per schema by payload.required. See Payload Contract for the full input → storage → replay mapping.


Operations: Notify, Watch, Replay

Aviso exposes three operations, each on its own endpoint:

Notify: POST /api/v1/notification

Publishes a notification to the backend. The identifier must match all required schema fields exactly (no wildcards, no constraints).

Watch: POST /api/v1/watch

Opens a persistent Server-Sent Events (SSE) stream. Receives live notifications as they arrive, optionally starting from a historical point.

  • Omit from_id/from_date for a live-only stream.
  • Provide one of them for historical replay first, then live.

Replay: POST /api/v1/replay

Opens a finite SSE stream of historical notifications only. Requires exactly one of from_id or from_date. Stream closes automatically when history is exhausted.

For end-to-end working examples of all three operations, including spatial and constraint filtering, see Practical Examples.


CloudEvents

Aviso delivers notifications to watch/replay clients as CloudEvents, a standard envelope format. Each event includes:

  • id: the backend sequence reference (e.g. mars@42), used for targeted delete or resume.
  • type: the Aviso event type string, prefixed with int.ecmwf.aviso. (for example int.ecmwf.aviso.mars).
  • source: the server base URL.
  • data.identifier: the canonicalized identifier.
  • data.payload: the notification payload (or null if omitted).

Backend

The backend is the storage and messaging layer that Aviso delegates to. Two backends are supported:

BackendUse case
jetstreamProduction: durable, replicated, persistent history
in_memoryDevelopment: fast setup, no persistence

The backend is selected via notification_backend.kind in config. See Backends Overview.