analyzing-insights-across-teams

oleh posthog

Analyze PostHog insights, dashboards, or teams beyond the current project by querying the prod Postgres replicas synced into the dogfood data warehouse (US…

npx skills add https://github.com/posthog/posthog --skill analyzing-insights-across-teams

Analyzing insights across teams

system.* entity tables (e.g. system.insights) are scoped to the current project, and the generic execute-sql guidance says other teams' data is inaccessible. For the dogfood project (US project 2) that is not the whole story: production Postgres tables are replicated into the project's data warehouse, so cross-team entity metadata is queryable with posthog:execute-sql. Do not stop at system.insights when the question spans teams.

This skill is deliberately repo-local (.agents/skills/): it documents PostHog's internal dogfood setup, applies only to agents working in this repo, and must not move into the packaged products/*/skills/ bundle that ships to every team.

Synced tables

EntityUS (prod-us)EU (prod-eu)
Insightspostgres.posthog_dashboarditemeu_postgres_posthog_dashboarditem
Dashboardspostgres.posthog_dashboardeu_postgres_posthog_dashboard
Teams / projectspostgres.posthog_teameu_postgres_posthog_team
  • Underscore aliases (e.g. postgres_posthog_dashboarditem) point at the same synced data.

  • These are replicas of the Django tables in this repo (posthog_dashboarditem backs the Insight model), so rows span every team; team_id is the scoping column.

  • More prod tables than these are synced. Before concluding cross-team data is inaccessible, check the catalog:

    SELECT table_name, description
    FROM system.information_schema.tables
    WHERE table_type = 'data_warehouse' AND table_name ILIKE '%postgres%'
    

Workflow

  1. Confirm columns before projecting — synced schemas drift with the Django models:

    SELECT column_name, data_type
    FROM system.information_schema.columns
    WHERE table_name = 'postgres.posthog_dashboarditem'
    
  2. Query with posthog:execute-sql, filtering or grouping by team_id. Example — most active teams by insights created in the last 30 days:

    SELECT team_id, count() AS insights_created
    FROM postgres.posthog_dashboarditem
    WHERE NOT deleted AND saved AND created_at >= now() - INTERVAL 30 DAY
    GROUP BY team_id
    ORDER BY insights_created DESC
    LIMIT 20
    

    Join postgres.posthog_team on id = team_id for team names only when the output stays on an internal surface (see below).

  3. Remember the sync lag: these are periodic replicas, not live reads — fine for analysis, not for "right now" state.

Output handling (required)

Rows in these tables are customer data: team names, insight names, descriptions, and queries.

  • Never put customer team names, insight titles, or other row-level metadata on public surfaces — PR titles/descriptions, commit messages, issues, code comments, or uploaded screenshots. Aggregates and team_id-level figures without names are the ceiling for public copy.
  • Keep named results in the private conversation, internal docs, or auth-gated links.
  • Access is gated by membership in the internal dogfood project. If a query fails with a permissions error, report it and stop — do not look for another route to cross-team data.

Related

  • For cross-team event/analytics data (not entity metadata), see the query-clickhouse-via-metabase skill instead.

Lebih banyak skill dari posthog