PostHog / PostHog/posthog

feat(data-management): surface references to undefined or stale events sooner than 30 days, and everywhere they are used

Open
#100,930 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement feature
Dominant language
Python
Stars
39.9k
Forks
3.4k
Avg merge
6h 51m
Merged PRs (30d)
232

Description

Is your feature request related to a problem?

The UI treats event definitions as the source of truth (pickers, actions, insights, schema management), but nothing enforces that a saved object still points at an event that exists or is still arriving. An action or insight whose event was retired, renamed, or mistyped looks identical to a healthy one and quietly charts zero. Teammates read that zero as real data.

#95863 (merged 2026-09-08) closed the first gap for actions: a "Not seen" tag when the event has no definition, and a "Stale" tag when the definition exists but the event has not arrived in 30 days. #99899 (draft) extends the same warning to insight series. A customer who reported the original gap (ticket 71245, internal) came back with two objections that neither PR addresses:

  1. 30 days is too slow for the "stopped arriving" case. The threshold is a single hardcoded constant, STALE_EVENT_DAYS = 30 in frontend/src/lib/constants.tsx:141, shared with the taxonomic picker. A daily event that dies is invisible for a month; a monthly event is never "stale" by design. There is no per-project or per-event setting.
  2. "Not defined" should be an actionable state, not a per-object tag. Their framing: PostHog ingests unstructured events by default, which is fine, but once a team has defined its events in the UI, anything referencing an event outside that set should be flagged for someone to action. Today the signal only appears where a person happens to look (an action's row, soon an insight series). There is no single place that lists every object pointing at an event that is no longer defined.

Describe the solution you'd like

  1. Configurable staleness threshold. A project-level setting (default 30 days) and an optional per-event override on the definition, replacing the hardcoded constant. Both isDefinitionStale callers, the taxonomic picker and the event health warning, read the configured value, so a team that knows its events are daily can be warned in days rather than a month.
  2. One view of references to undefined events. A list under Data management of actions, insights, cohorts, and experiments whose event has no definition (and, secondarily, is stale), so "not defined" becomes something a team can review and action in one place instead of discovering per object. The building blocks exist: the references endpoint actions already have (/actions/:id/references/) and the batched event_definitions?names= lookup actionEventHealthLogic uses.

Describe alternatives you've considered

  • Insight alerts with a lower bound ("less than 1") on each insight that uses the event or action. Works today, but it is per insight, must be set up in advance, and says "value dropped" rather than "the event is no longer defined".
  • Schema management (schema-management flag, 100% rollout; docs mark it experimental). It lets a team define events and property groups upfront and validates the properties of defined events at ingestion, but validate-event-schema.ts passes any event with no schema straight through, so it cannot flag unknown event names or dangling references.
  • Marking retired events Hidden instead of deleting them. Keeps them out of pickers, but does nothing for objects that already reference them.
  • Lowering the constant globally. Would cause false "Stale" tags on legitimately infrequent events; the picker already had to add an explicit opt-in for stale results (#59816) because of this trade-off.

Additional context

  • Shipped: #95863 "warn when an action's event stopped arriving" (tags on actions list and step editor, prod since 2026-09-09).
  • In flight: #99899 "flag insight series whose event stopped arriving" (draft).
  • Related requests: #44658 Schema Management feature requests (aggregator), #31440 enforce consistency when creating custom events, #23979 native schema enforcer.
  • Definition deletion is cosmetic: rust/property-defs-rs/src/batch_ingestion.rs re-creates the row on the next matching event (INSERT … ON CONFLICT DO UPDATE). So "Not seen" only fires for events that genuinely stopped or never existed, and the 30-day stale path carries the whole "stopped arriving" case, which is why the threshold matters.
  • Raised by a customer, ticket 71245 (internal).

Debug info

  • PostHog Cloud, region and project ID: EU, project 14109 (customer); behaviour verified on master @ f36dd2de2
  • PostHog Hobby self-hosted with docker compose, version/commit: n/a
  • PostHog self-hosted with Kubernetes (deprecated), version/commit: n/a

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with frontend/src/lib/constants.tsx and trace both isDefinitionStale callers, including the taxonomic picker and event health warning. Read the existing action references endpoint and actionEventHealthLogic's batched event_definitions lookup before deciding how the project and per-event settings connect to a unified Data management view. Done means configurable thresholds and one reviewable list covering the named object types.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, data, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.