Event ingestion filtering

Event ingestion filtering lets you drop events at ingestion time based on event metadata. Filters are evaluated early in the ingestion pipeline, before transformations run, making it the most efficient way to exclude unwanted events from your data.

Common use cases include:

  • Dropping events from automated bots or internal tools
  • Filtering out test or staging traffic by distinct_id
  • Removing high-volume, low-value events to reduce costs
  • Temporarily filtering buggy data while you roll out a client-side fix

You can find it at Data management > Event filtering.

How it works

Each incoming event is evaluated against a set of conditions you define. If an event matches the filter, PostHog drops it before ingestion. If it doesn't match, it continues through the pipeline as normal.

Filters run before transformations and destinations, so dropped events don't trigger any downstream processing.

If your filtering logic can be expressed here, we recommend using event ingestion filtering over a drop events transformation. It runs earlier in the pipeline and doesn't require writing custom code.

Operating modes

The filter has three modes:

ModeBehavior
DisabledNo filtering is applied. All events are ingested normally.
Dry runMatching events are counted but not dropped. Use this to validate your filter before going live.
LiveMatching events are dropped from ingestion.

We recommend starting with dry run mode and checking the metrics to confirm your filter is matching the right events before switching to live.

Creating a filter

Filters are built using a visual expression builder that supports nested boolean logic (AND, OR, NOT).

Each condition has three parts:

  1. Field – what to match on:

    • event_name – the name of the event (e.g., $pageview, signup)
    • distinct_id – the distinct ID attached to the event
  2. Operator – how to match:

    • equals – the field value matches the specified value exactly
    • contains – the field value contains the specified string
  3. Value – the string to match against

Combining conditions

  • AND groups match when all conditions in the group are true.
  • OR groups match when any condition in the group is true.
  • NOT negates a group, matching when the group's conditions are not true.

You can nest groups up to five levels deep and add up to 20 conditions total. Conditions and groups can be reordered using drag and drop.

Example: To drop all $pageview events from a bot with distinct ID containing bot-crawler:

AND
├── event_name equals "$pageview"
└── distinct_id contains "bot-crawler"

Example: To drop events from multiple internal tools:

OR
├── distinct_id contains "internal-tool-a"
└── distinct_id contains "internal-tool-b"

Test cases

Events dropped by a filter can't be recovered, so verify your filter works correctly before turning it on. Test cases help you do this – they validate the filter against example events and serve as living documentation of what the filter is intended to match.

Each test case specifies:

  • An event name
  • A distinct ID
  • The expected result – either "Drop" or "Ingest"

Test cases run locally in your browser and show a pass/fail result. The filter can't be enabled until all tests pass – if you try to save in live mode with failing tests, it automatically downgrades to dry run.

Metrics

The event filtering page shows approximate counts of:

  • Dropped – events the filter dropped in live mode
  • Would be dropped – events the filter matched in dry run mode (not actually dropped)

Use these metrics to validate your filter is matching the right volume and type of events before going live.

Note: Metrics are processed on a best-effort basis and may be off by a small percentage.

Limits

  • Maximum 20 conditions per filter
  • Maximum five levels of nesting
  • Only event_name and distinct_id fields are supported
  • Only equals and contains operators are supported
  • One filter configuration per project

Further reading

Community questions

Was this page useful?

Questions about this page? or post a community question.