Drizzle Cube: An Embeddable Semantic Layer for SaaS Apps
For a large part of my career I have been involved in or around ensuring that we can get data from our systems and applications into a form and location where they can create insights for ourselves or our customers.
When I was the CTO at the DailyMail I built a real time analytics dashboard that allowed journalists and editors to see exactly how the changes they made to their articles and landing pages optimised traffic to and from them, allowing us to grow from 55M monthly uniques to over 200M by the time I left in 2014.
At TES we built an entire data lake on Redshift and self-service reporting platform based on Looker, that powered the entire business be it news, jobs, teaching resources or at the time the burgeoning B2B software business (now much larger in scale).
At Infinitas we have done something similar, but we use Snowflake, and have most of our reporting by PowerBI (which I will be glad to one day never use again). One thing we haven’t (yet) done here is really leverage all the data we have to deliver real insight back to the schools that use our products - though its something we are actively thinking about.
In addition to all of this direct hands on experience, I have also spent a lot of time in and around different tools for reporting over the years - looker, metabase, superset, redash, powerbi, mixpanel, amplitude … etc etc. And one of the biggest challenges you encounter (and I think largely unsolved esp. in the open source variety) is “How can I share self-service analytics with my customers in a scalable, secure and maintainable way?”.
There are solutions now in this space - like Embeddable or Cube.dev - but these are all paid solutions (albeit in the case of Cube one with an open core). So I thought, with my new found AI super powers why can’t I build one?
Enter Drizzle-Cube
The idea was sparked from the need above, and the approach came to me with a simple question:
- Drizzle is a great DB abstraction library for typescript, with a very expressive and usable API.
- Cube.dev has a clear and usable Query format for this use case Cube-js Query Format.
- What if I can build a library, that can be embedded in any existing typescript application, that offers an out of the box interface to execute Cube queries on an existing database.
- … and off we went.
So over a few weekends and early mornings, heavily leveraging Claude Code, I worked through the fundamentals and built a first working version. It is now public.
Some of the things it provides out of the box are:
An engine and API with an analytics semantic layer for your database
A semantic layer sits between your raw data and your users, providing a business-friendly abstraction that transforms complex database schemas into intuitive, queryable concepts. Instead of writing SQL against tables like user_activities
and subscription_events
, your users can ask questions like “show me monthly recurring revenue by customer segment” or “what’s our user retention rate this quarter?”
This is defined in code via Cubes: Cube Definitions. These are based on existing Drizzle schema definitions, but even if you dont currently use Drizzle you can create a new micro-service on top of your existing database (either a transactional or reporting database), and drizzle-kit pull extract the schema from it to then use in Drizzle Cube.
Once you do this, and then add an adapter to quickly add the new API endpoints and wire it int your schema and semantic layer (currently we have one for Express, Hono, Fastify and NextJS) and then you get a rest API to query your data:
// Query exampleconst query = { measures: ['Sales.totalSales', 'Sales.orderCount'], dimensions: ['Sales.productCategory'], timeDimensions: [{ dimension: 'Sales.orderDate', granularity: 'month' }], filters: [{ member: 'Sales.orderDate', operator: 'inDateRange', values: ['2024-01-01', '2024-12-31'] }]};
// Make request to your new cube-js API (provided by drizzle-cube)const response = await fetch('/cubejs-api/v1/load', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(query)});
const data = await response.json();console.log(data);
A rich set of UI components that let you quickly build solutions on top
I have built a default set of Providers, Hooks and React components, that use Tailwind for styling. You can either use these directly or copy-paste into your own codebase and modify, you can see the info here.
Query Builder
There is an embeddable query builder, including AI features (the CubeJS query language is very simple, so based on the Cube definitions it can easily generate queries based on natural language inputs).
AI Query Builder
Using AI (in this case Gemini) to create even fairly complex queries from natural language:
Dashboards
And then of course what you really want is the ability for users to create their own dashboards, so there is a complete dashboard component, with drag / drop for portlets, and complete configurability (using the query builder) for users to create, test, and configure their own rich dashboards:
And editing a portlet is as easy as:
How does it work?
Good question. I have written a detailed overview here: https://www.drizzle-cube.dev/help/getting-started/how-it-works. And of course you could also read the code!
So whats next
I want to find some real world users - perhaps I will use it internally in my day job - to see if it can also solve problems for others. So if this might be you then I will be really happy to assist where I can. Otherwise I will keep working in my spare time to improve the quality, add support for more databases, share it with others and continue to enjoy building something!
You can of course try it here: Drizzle Cube.
The code (MIT Licensed) is here: Github Repository.