Lyrebird Engineering
Data Platform Deep dive · 9 min read

Making data work for everyone, not just the data team

We built four self-service interfaces that let every team at Lyrebird answer their own questions. Here is the architecture, the trade-offs, and the governance layer that makes it trustworthy enough to act on.

For a while, the Lyrebird data team was doing really well by one measure: we were answering every question that came in. MRR trends for leadership, risk scores for CS, pipeline health for product, usage breakdowns for the founders. Fast turnaround, accurate numbers, nobody complaining.

The problem was that answering questions had quietly become the job. We were not building. We were a lookup service.

The cost was invisible on any roadmap. It showed up as decisions made without data because our queue was too long. It showed up as a CS lead who knew a GP was at risk but could not pull usage data without filing a ticket. It showed up as leadership getting their weekly metrics on Wednesday, two days after the week they were meant to inform.

The question worth asking: what would change if our job was to build infrastructure that lets other people answer their own questions, rather than answering them one by one? That reframing shaped everything we built next.

01

What we mean by self-service

Self-service data gets misunderstood. It does not mean giving everyone a SQL editor and a warehouse connection. We tried that. A product manager ended up writing SQL at 11pm, getting a subtly wrong answer because they joined on the wrong key, and presenting it to leadership with confidence. That is not self-service. That is distributed data debt.

Real self-service means the interface is shaped to the consumer. The question a CS lead needs to answer Monday morning is different from what a PM needs for a roadmap review. The underlying data is the same. The surface has to fit the job.

We built four of these interfaces. Each one is designed around a specific person, a specific decision, and a specific cadence.

Fig 1 · One data layer, four surfaces
01
GP risk report
CS team · Claude skill · every Monday morning
02
Weekly Business Review
Leadership · automated delivery · pre-meeting
03
Product engagement
WAU · feature depth · activation signals
04
Conversation intelligence
Sales · Gong joined to product metrics
One governed semantic layer

Fig 1. All four surfaces query the same semantic layer. Definitions stay consistent regardless of which interface is used.

02

The four interfaces

01The GP risk report

Our CS team works a list. Every week, they need to know which GPs are at risk, why, and who to contact first. Before we built this, that answer came from a ticket, a two-day wait, and a Slack message with a spreadsheet attached. By the time the CS lead saw it, some of those GPs had already churned.

We built a Claude skill for the CS team. They open it on Monday morning, ask which GPs are at risk this week, and get back a prioritised list classified by behavioural signals: weekly active usage (WAU) trends, usage patterns, days since last active, MRR exposure. Critical, High, Medium, Watch. No ticket, no query, no waiting for the data team. They self-serve it.

The data was always there. What changed was when it arrived and who it reached.

Fig 2 · GP risk tiers, weekly classification
CriticalNo activity this week. MRR fully exposed, immediate outreach required.
HighSharp WAU decline. Significant drop week on week, prioritise this week.
MediumGradual engagement decline. Softening usage, monitor closely.
WatchEarly warning signals. First signs of disengagement, flag for next cycle.

Fig 2. Each tier has a defined action. The Claude skill surfaces movement between tiers week on week.

02The Weekly Business Review

Leadership used to spend 2 to 3 hours on Monday mornings pulling metrics from six different places, reconciling the numbers, and formatting the document before a meeting that needed those numbers to be useful. By the time it was done, the meeting had started.

We automated it. The WBR now runs on a schedule: it queries the semantic layer, builds the tables, and distributes the document before anyone is at their desk. The automation did not just save three hours. It changed the rhythm of the business. A leadership team that gets accurate metrics before their weekly discussion makes different decisions than one that gets them on Wednesday morning.

03Product engagement

Understanding how GPs actually use the product was the missing layer between acquisition and revenue. We had conversion data. We had usage data. But they lived in separate places and the connection between them was never visible.

We built the product engagement layer on top of the same semantic foundation. It tracks weekly active usage across the GP base, feature depth across consult notes, document outputs, and workflows, and maps those signals to downstream conversion and retention outcomes.

Product, sales, and CS can now query this directly. Which GPs are approaching the activation threshold. Which features a GP has and has not adopted. Where in the depth curve a GP is sitting in any given week. That information used to require a data request. Now it is a question in a Claude skill.

04Conversation intelligence

Most sales teams have a version of this problem: the call data lives in Gong, the product usage data lives in the warehouse, and nobody can connect them. So you end up with two separate narratives. Sales sees what was said on the call. Product sees what happened in the product afterwards. Neither sees the full picture.

We joined the Gong call data to our weekly product metrics. What that unlocks is the ability to track how a sales conversation actually affects downstream GP behaviour. Did the GPs who heard a specific pitch activate faster? Which conversation patterns predict a GP becoming a paying customer?

These are questions the business always wanted to answer. The data to answer them existed in two separate systems. Joining them in the governed semantic layer meant the whole funnel became visible in one place.

03

Connecting it all

The individual interfaces each solve one problem. The GP risk report tells CS who to call. The WBR gives leadership a consistent view of the business. The product engagement layer shows how GPs are actually using the product. The Gong data captures what happened in the conversations before they became customers.

What we did not expect was how much more useful each became once they were on the same foundation. When your sales conversation data and your product usage data share a semantic layer, questions that previously had no answer become queryable. Not because the data was not there before. It was. It just lived in systems that had never been connected, with definitions that had never been aligned.

Fig 3 · How the data platform connects
Source systems
StripeBest Practice EMRGongLinearProduct DBIntercom
extract + load
dbt transformation layer
Staging → Marts → BI. Tested, versioned, CI/CD on every PR.
deploy
Snowflake semantic views
WBR metrics · Activation · Engagement · Churn. One definition each.
read through the layer
Every consumer
BI dashboardsClaude skillsAutomation · WBR + risk reportAI agents · Claude via MCP

Fig 3. Every consumer reads through the semantic layer. One definition, consistent everywhere.

The value of the governed layer is not that it makes any single dataset more useful. It is that it makes every dataset composable. A question that crosses two domains becomes one query. That shift in what is possible to ask is what changes the relationship between the business and its data. Teams stop waiting for answers and start building on the infrastructure themselves.

04

The governance layer that makes it trustworthy

Self-service breaks without consistent definitions. The moment three people pull "activation rate" and get three different numbers, trust collapses. Once trust collapses, we are back to answering questions.

Governance is the infrastructure that prevents that. Not policies, not documentation, not a data dictionary nobody reads. Structural constraints enforced at the warehouse level.

Every metric is defined exactly once: activation_rate, wau_churn, mrr_at_risk. Every consumer of the semantic layer gets the same answer, regardless of which BI tool they use or which interface they query through. The semantic view enforces the definition. The semantic view is the definition.

models/semantic/activation.yml yaml
# one definition, read by every BI tool, skill, and agentmetric:  name: activation_rate  type: ratio  numerator: activated_gps        # first note saved in-app  denominator: signed_up_gps  exposed_to: [bi, claude_skills, agent]

The metric, defined once. Every surface reads activation_rate from here, so it means the same thing in a dashboard, a Claude skill, and the agent. Illustrative shape, not our exact schema.

Each team also sees only the data they need. Revenue tables, billing data, and PII are restricted at the warehouse level, not filtered by a dashboard setting that someone could misconfigure or override.

Fig 4 · The two roles
Admin role deploy-time

Used by the data team to deploy infrastructure. Creates semantic views, manages grants, configures the MCP server.

Never used at query time · runs in Terraform · version-controlled
Analyst role runtime · read-only

What Claude authenticates as at runtime. Can read from semantic views only. Explicit table allowlist enforced.

Anything outside the allowlist returns an access error · never sees raw source tables

Fig 4. The admin role builds the infrastructure. The analyst role, which is what Claude uses, can only read through the governed layer.

05

The same architecture, applied to AI

Once we had a governed semantic layer for human analysts, connecting an AI agent was a natural next step. Claude can now query the governed Snowflake data through MCP. But the governance architecture matters even more here than it does for humans.

When a human analyst queries the wrong table, you find out in the PR review or the data quality check. When an AI agent queries the wrong table, it might return a result that looks plausible, and that result might inform a decision before anyone notices.

A system prompt is not a governance boundary. It can be overridden, misunderstood, or simply ignored. The boundary has to live in the infrastructure.

Fig 5 · How Claude queries at runtime
Claude receives a natural-language question
From CS, product, sales, or leadership via a Claude skill.
authenticates via MCP server
Analyst role enforced
Explicit table allowlist checked. Anything outside returns an access error, not a result.
Semantic views queried
Metric definitions enforced. activation_rate means the same thing here as in every BI tool.
Curated dbt layer
Pre-joined context, sensitive columns already stripped, auto-granted on prod deploy.
source tables never touched directly
Source tables (blocked)
Revenue · billing · PII. The agent role has no grants here.

Fig 5. Every layer enforces a boundary. The agent cannot step outside them, accidentally or deliberately.

analyst role · runtime sql
agent> SELECT * FROM raw.stripe_invoices;

✗ access control error
  role AGENT_ANALYST has no SELECT on RAW.STRIPE_INVOICES
  the query never runs

The refusal, in practice. The boundary is the database grant, not the prompt. The agent asks, the warehouse says no, and no data moves.

Three failure modes this makes structurally impossible:

01
Data leakage
The agent tries to query a revenue or PII table. The database returns an access error. The query never runs.
02
Definition drift
The agent invents its own calculation for activation rate. It cannot. It can only read the semantic view, which enforces the definition.
03
Compute saturation
An expensive agent query spikes compute. It runs on the isolated agentic warehouse. Production pipelines are unaffected.

The whole pattern, which is to say roles, grants, semantic view definitions, and warehouse config, is version-controlled in Terraform. Access controls are reviewable in a pull request like any other infrastructure change. When someone asks what the agent can see, the answer is in the repo, not someone's memory.

governance/analyst_role.tf terraform
# reviewed in a pull request like any other infra changeresource "snowflake_database_role" "agent_analyst" {  database = "ANALYTICS"}# the agent reads the governed layer, and nothing elseresource "snowflake_grant_privileges" "reads" {  privileges = ["SELECT"]  on_schema  = "ANALYTICS.SEMANTIC"   # semantic views only}# no grants on raw tables: revenue, billing, and PII stay out of reach

Governance as code. What the agent can and cannot reach is a diff, reviewed like any other change. Illustrative, not our exact config.

06

What we learned

The shift from "answer people" to "infrastructure team" did not happen in a sprint. It happened gradually, in the space between tickets. Every time we automated something we had been doing manually. Every time we built an interface instead of answering a question.

Governance enables self-service. It does not restrict it. Before the semantic layer, we were nervous about giving teams direct access because we could not guarantee the numbers were right. After it, we were actively pushing teams to use the data themselves.

The best signal that it was working: the sales team built their own GTM dashboards. Product managers started creating Claude skills against the governed data. Nobody asked permission. That is the outcome. Not a metric, but other people building things because the infrastructure made it possible.

If building infrastructure that other teams actually want to use sounds like your kind of problem, we are hiring engineers on the Data Platform team.

Build with us

Come build clinical AI worth trusting.

We are hiring engineers who care about getting the hard parts right, from the data platform to the product clinicians rely on every day.