---
title: "Validate every event before you store it · Agent Wranglers"
url: https://agentwranglers.se/playbook/analytics/events-and-metrics/event-validation
id: ANA-2
level: Recommended
updated: 2026-10-27
build: a2a6bdfed830
tokens: 950
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Validate every event before you store it

For AI agents: the [site map](https://agentwranglers.se/llms.txt) lists everything here, and this page sits under [Events and metrics](https://agentwranglers.se/playbook/analytics/events-and-metrics.md).

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers.md). Updated 2026-10-27.

- ID: ANA-2
- Level: Recommended
- Chapter: [Events and metrics](https://agentwranglers.se/playbook/analytics/events-and-metrics.md)
- Rule: Check each incoming event against its schema at the collector. Store valid events, and set invalid ones aside with the reason.
- Check: Send one valid and one invalid event to the staging collector. The valid one is in the events table, and the invalid one is in the rejects table with its error.
- How: Compile the tracking plan into JSON Schema 2020-12 validators, such as Ajv's `Ajv2020` class or Python's `jsonschema`. Reject unknown events, unknown properties and wrong types. Write rejects to a separate table with the error and the app version, as with a [dead letter queue](https://agentwranglers.se/playbook/events/background-jobs-and-queues/dead-letter-queue.md). Alert when rejects pass 1 percent of events in an hour, because a release has broken tracking. It is the [parse at the boundary](https://agentwranglers.se/playbook/architecture/data-shapes/parse-at-the-boundary.md) rule applied to events.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### JavaScript example

```js
import Ajv2020 from 'ajv/dist/2020.js';

const ajv = new Ajv2020({ allErrors: true });
const validators = Object.fromEntries(Object.entries(EVENT_SCHEMAS).map(([name, schema]) => [name, ajv.compile(schema)]));

export async function collect(event) {
  const validate = validators[event.name];
  if (validate?.(event.properties)) return db.events.insert(event);
  return db.eventRejects.insert({ event, error: validate ? ajv.errorsText(validate.errors) : 'unknown event' });
}
```

### Python example

```python
from jsonschema import Draft202012Validator

VALIDATORS = {name: Draft202012Validator(schema) for name, schema in EVENT_SCHEMAS.items()}

def collect(event: dict):
    validator = VALIDATORS.get(event["name"])
    errors = [e.message for e in validator.iter_errors(event["properties"])] if validator else ["unknown event"]
    if errors:
        return db.event_rejects.insert(event=event, error="; ".join(errors))
    return db.events.insert(event)
```

## Sources

- [JSON Schema 2020-12](https://json-schema.org/draft/2020-12)

## Related rules

- EVT-23 [Set aside messages that keep failing](https://agentwranglers.se/playbook/events/background-jobs-and-queues/dead-letter-queue.md) in Integration and events
- ARC-53 [Parse input once at the boundary](https://agentwranglers.se/playbook/architecture/data-shapes/parse-at-the-boundary.md) in Clean code and architecture

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/analytics/events-and-metrics/event-validation">Agent Wranglers product analytics and experiments playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Keep a tracking plan in the code](https://agentwranglers.se/playbook/analytics/events-and-metrics/tracking-plan.md)
- Next: [Record business facts on the server](https://agentwranglers.se/playbook/analytics/events-and-metrics/server-side-business-events.md)
- [Events and metrics](https://agentwranglers.se/playbook/analytics/events-and-metrics.md)
