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.
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. All four surfaces query the same semantic layer. Definitions stay consistent regardless of which interface is used.
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. 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.
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. 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.
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.
# 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.
Used by the data team to deploy infrastructure. Creates semantic views, manages grants, configures the MCP server.
What Claude authenticates as at runtime. Can read from semantic views only. Explicit table allowlist enforced.
Fig 4. The admin role builds the infrastructure. The analyst role, which is what Claude uses, can only read through the governed layer.
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. Every layer enforces a boundary. The agent cannot step outside them, accidentally or deliberately.
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:
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.
# 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.
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.