Product Analytics ER diagram and database schema
The Product Analytics database schema is a DB Planner template with 27 tables, 214 columns and 48 relationships, free to use. Core tables include api_keys, cohort_memberships, cohorts, daily_event_rollups. It can be opened as an interactive ER diagram or exported as PostgreSQL, MySQL, or SQL Server DDL.
- Tables
- 27
- Columns
- 214
- Relationships
- 48
- Category
- Analytics
- Exports
- DBML, SQL, C#
- Price
- Free
What this schema models
A complete product analytics database design, the kind of data model behind a tool similar to Mixpanel: 27 tables, 13 enums and 48 relationships covering workspaces, projects and API keys, anonymous devices and identified persons with an identity alias graph, person property history, sessions, a raw event log with an event and property registry, daily rollups, feature flags with targeting rules, experiments with variants and exposures, funnels, versioned cohorts, saved reports and dashboards. THE FOUR DESIGN RULES 1. Raw events are immutable. events is append-only, partitioned by month on occurred_at, with a client-generated id so a retried batch is deduplicated. Sessions, rollups, cohorts and report results are all derived, and can be rebuilt from it. 2. Identity resolves through aliases, never by rewriting events. Every event keeps the distinct_id it was sent with; identity_aliases maps each distinct id to a person. When an anonymous visitor logs in or two persons merge, only alias rows change, and the whole history follows. 3. What happened is separate from what it means. Events carry raw names and JSONB properties; event_definitions and property_definitions add display names, descriptions, types, PII flags and a verified or hidden status. Definitions are created automatically on first sight, so tracking is never blocked by governance, and renaming an event never touches a row of data. 4. Derived data is cached or versioned, never half-built. A cohort recompute writes membership version n+1 in full and then flips current_version in one update; persons.properties is a cache folded from person_property_changes; a report result is only ever a cache of its stored query. DETAILS WORTH STEALING - Daily rollups keep a HyperLogLog sketch beside the count, because distinct users cannot be added across days but sketches can be merged. - Feature flags bucket users by hash(key + salt + distinct id), so assignment is deterministic, needs no stored rows, and SDKs can evaluate flags locally. - Experiments log exposure when the variant is first seen, not when the user is bucketed, so people who never reached the changed screen do not dilute the result; the primary metric is fixed before launch. - First-touch attribution (referrer and UTM tags) lives on the device, because it happened before identity did. - Ingestion keys are public and write-only, secret keys read data, and both are stored only as hashes. - Person property history answers "what plan were they on when they did that?" WHAT YOU GET Clean DBML that imports directly into DB Planner, and a laid-out board with zones color-coded and framed: workspaces and access, identity and sessions, events and registry, flags and experiments, cohorts and funnels, and dashboards and reports. Every table carries a note. Written for Postgres: event and person properties, flag rules, cohort and funnel definitions and saved queries are jsonb (JSON in MySQL, NVARCHAR(MAX) in SQL Server), and the raw events table is meant to be partitioned by time. Useful for developers building in-house analytics or an analytics product, and for students who need a realistic product analytics ER diagram for a DBMS project. This is a schema design reference; at real event volumes the events table usually moves to a columnar store while the shape stays the same.
Tables (27)
| Table | Columns |
|---|---|
| api_keys | 10 |
| cohort_memberships | 3 |
| cohorts | 10 |
| daily_event_rollups | 7 |
| dashboard_tiles | 8 |
| dashboards | 8 |
| devices | 11 |
| event_definitions | 11 |
| event_property_usage | 4 |
| events | 12 |
| experiment_exposures | 5 |
| experiment_variants | 5 |
| experiments | 12 |
| feature_flags | 10 |
| flag_rules | 7 |
| funnel_steps | 5 |
| funnels | 9 |
| identity_aliases | 6 |
| person_property_changes | 6 |
| persons | 8 |
| projects | 6 |
| property_definitions | 9 |
| saved_reports | 12 |
| sessions | 16 |
| users | 4 |
| workspace_members | 4 |
| workspaces | 6 |
Relationships (48)
api_keys.created_by references users.idmany to oneapi_keys.project_id references projects.idmany to onecohort_memberships.cohort_id references cohorts.idmany to onecohort_memberships.person_id references persons.idmany to onecohorts.created_by references users.idmany to onecohorts.project_id references projects.idmany to onedaily_event_rollups.project_id references projects.idmany to onedashboard_tiles.dashboard_id references dashboards.idmany to onedashboard_tiles.saved_report_id references saved_reports.idmany to onedashboards.created_by references users.idmany to onedashboards.project_id references projects.idmany to onedevices.person_id references persons.idmany to onedevices.project_id references projects.idmany to oneevent_definitions.owner_user_id references users.idmany to oneevent_definitions.project_id references projects.idmany to oneevent_property_usage.event_definition_id references event_definitions.idmany to oneevent_property_usage.property_definition_id references property_definitions.idmany to oneevents.project_id references projects.idmany to oneexperiment_exposures.experiment_id references experiments.idmany to oneexperiment_exposures.variant_id references experiment_variants.idmany to oneexperiment_variants.experiment_id references experiments.idmany to oneexperiments.created_by references users.idmany to oneexperiments.primary_funnel_id references funnels.idmany to oneexperiments.project_id references projects.idmany to oneexperiments.winning_variant_id references experiment_variants.idmany to onefeature_flags.created_by references users.idmany to onefeature_flags.id references experiments.feature_flag_idone to onefeature_flags.project_id references projects.idmany to oneflag_rules.cohort_id references cohorts.idmany to oneflag_rules.feature_flag_id references feature_flags.idmany to onefunnel_steps.funnel_id references funnels.idmany to onefunnels.created_by references users.idmany to onefunnels.project_id references projects.idmany to oneidentity_aliases.person_id references persons.idmany to oneidentity_aliases.project_id references projects.idmany to oneperson_property_changes.person_id references persons.idmany to onepersons.merged_into_id references persons.idmany to onepersons.project_id references projects.idmany to oneprojects.workspace_id references workspaces.idmany to oneproperty_definitions.project_id references projects.idmany to onesaved_reports.cohort_id references cohorts.idmany to onesaved_reports.created_by references users.idmany to onesaved_reports.funnel_id references funnels.idmany to onesaved_reports.project_id references projects.idmany to onesessions.device_id references devices.idmany to onesessions.project_id references projects.idmany to oneworkspace_members.user_id references users.idmany to oneworkspace_members.workspace_id references workspaces.idmany to one
How to use this template
- Open the ER diagram to see the tables and how they relate.
- Copy it into your workspace. You get your own editable copy, in DBML.
- Export it as PostgreSQL, MySQL, or SQL Server DDL, or as C# models.
The copy opens in DB Planner’s ER diagram tool, with the schema as text in the DBML editor beside it. Have a database already? Turn its SQL into an ER diagram instead.
Frequently asked questions
- What is in the Product Analytics database schema?
- 27 tables and 48 relationships, across 214 columns. The table names and the full relationship list are shown on this page.
- Can I export it to PostgreSQL or MySQL?
- Yes. Every DB Planner template exports as DBML, as PostgreSQL, MySQL, or SQL Server DDL, and as C# models.
- Is this template free?
- Yes. You can open it in the browser without an account, and copy it into your own workspace with a free DB Planner account.
- Can I change it after copying it?
- Yes. A copy is yours: you can rename tables, add columns, and export it. Changes the author makes later do not affect your copy.