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
| Entity |
US (prod-us) |
EU (prod-eu) |
| Insights |
postgres.posthog_dashboarditem |
eu_postgres_posthog_dashboarditem |
| Dashboards |
postgres.posthog_dashboard |
eu_postgres_posthog_dashboard |
| Teams / projects |
postgres.posthog_team |
eu_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
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'
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).
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
querying-production-databases-via-metabase skill instead.
1---2name: analyzing-insights-across-teams3description: Analyze PostHog insights, dashboards, or teams beyond the current project by querying the prod Postgres replicas synced into the dogfood data warehouse (US project 2, "PostHog App + Website"). Use when asked to analyze insights across all teams or projects, another team's insights, or fleet-wide insight/dashboard usage — cases where `system.insights` only returns the current project's rows and the agent would otherwise report the data as inaccessible. Covers the synced table names for US and EU and the column-verification workflow.4---5
6# Analyzing insights across teams
7
8`system.*` entity tables (e.g. `system.insights`) are scoped to the current project,
9and the generic `execute-sql` guidance says other teams' data is inaccessible.
10For the dogfood project (US project 2) that is not the whole story:
11production Postgres tables are replicated into the project's data warehouse,
12so cross-team entity metadata **is** queryable with `posthog:execute-sql`.
13Do not stop at `system.insights` when the question spans teams.
14
15This skill is deliberately repo-local (`.agents/skills/`): it documents PostHog's internal dogfood setup,
16applies only to agents working in this repo, and must not move into the packaged `products/*/skills/` bundle that ships to every team.
17
18## Synced tables
19
20| Entity | US (prod-us) | EU (prod-eu) |
21| ---------------- | -------------------------------- | ----------------------------------- |
22| Insights | `postgres.posthog_dashboarditem` | `eu_postgres_posthog_dashboarditem` |
23| Dashboards | `postgres.posthog_dashboard` | `eu_postgres_posthog_dashboard` |
24| Teams / projects | `postgres.posthog_team` | `eu_postgres_posthog_team` |
25
26- Underscore aliases (e.g. `postgres_posthog_dashboarditem`) point at the same synced data.
27- 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.
28- More prod tables than these are synced. Before concluding cross-team data is inaccessible, check the catalog:
29
30 ```sql
31 SELECT table_name, description
32 FROM system.information_schema.tables
33 WHERE table_type = 'data_warehouse' AND table_name ILIKE '%postgres%'
34 ```
35
36## Workflow
37
381. Confirm columns before projecting — synced schemas drift with the Django models:
39
40 ```sql
41 SELECT column_name, data_type
42 FROM system.information_schema.columns
43 WHERE table_name = 'postgres.posthog_dashboarditem'
44 ```
45
462. Query with `posthog:execute-sql`, filtering or grouping by `team_id`. Example — most active teams by insights created in the last 30 days:
47
48 ```sql
49 SELECT team_id, count() AS insights_created
50 FROM postgres.posthog_dashboarditem
51 WHERE NOT deleted AND saved AND created_at >= now() - INTERVAL 30 DAY
52 GROUP BY team_id
53 ORDER BY insights_created DESC
54 LIMIT 20
55 ```
56
57 Join `postgres.posthog_team` on `id = team_id` for team names only when the output stays on an internal surface (see below).
58
593. Remember the sync lag: these are periodic replicas, not live reads — fine for analysis, not for "right now" state.
60
61## Output handling (required)
62
63Rows in these tables are customer data: team names, insight names, descriptions, and queries.
64
65- 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.
66- Keep named results in the private conversation, internal docs, or auth-gated links.
67- 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.
68
69## Related
70
71- For cross-team **event/analytics** data (not entity metadata), see the `querying-production-databases-via-metabase` skill instead.