Rami Abi Habib

Data
12
m
Notebooks Are Dead. Long Live The Notebook (Part 2)
In Part 1, i talked about why the notebook concept is powerful, why Jupyter's implementation broke it, and why AI agents need notebooks anyway. Now let me tell you what we actually did about it.
We Started Where Everyone Starts
We didn't start here. Like everyone, we started with Jupyter under the hood. And we hit every single problem i just described. I want to walk through the specific moments that forced our hand because i think they show why this matters even more for AI-native products than for traditional data science.
The Staleness Problem, But Worse
In a traditional notebook a data scientist knows to re-run downstream cells. They understand the dependency, it's part of the craft. Our users are business teams. They don't know what "downstream cells" means. They don't know there IS a dependency. They see a dashboard with numbers on it and assume those numbers are current. If those numbers are stale, we've failed them. Silently. For a product where the whole point is trustworthy answers for the whole company, that's existential.
With Jupyter, when the AI generates an analysis across several cells and then a user changes one thing, say they edit a filter or update a date range, only that one cell re-runs. Everything downstream is stale. The chart below still shows the old data. The summary metric at the bottom still reflects the old filter. Nothing indicates this. The user is looking at wrong numbers and doesn't know it.
In a traditional notebook a data scientist knows to re-run downstream cells. They understand the dependency, it's part of the craft. Our users are business teams. They don't know what "downstream cells" means. They don't know there IS a dependency. They see a dashboard with numbers on it and assume those numbers are current. If those numbers are stale, we've failed them. Silently. For a product where the whole point is trustworthy answers for the whole company, that's existential.
The Interactivity Wall
We needed interactive elements. A date picker that filters a SQL query that feeds a chart. A dropdown that switches between segments. A slider that adjusts a parameter. In Jupyter, cells are islands. The kernel protocol doesn't support two-way communication between UI elements and computation across cells. If you create a slider in Cell 1, there's no mechanism for Cell 5 to react when that slider moves. You'd have to hack it by sending code strings back and forth, which is fragile and slow and breaks constantly.
The State Fragmentation Problem
Our notebook state was scattered across three systems: Postgres (notebook structure), the kernel (runtime state), and the frontend (UI state). No single source of truth. We had race conditions where the frontend thought a cell had run but the kernel disagreed. Data loss on server restarts because the kernel state just evaporated. Bugs that were agonizing to debug because the state lived everywhere and nowhere at the same time.
The Debate That Changed the Company
We had a serious internal debate about this. Notebooks vs. DSLs vs. something else entirely. Weeks of thinking. Do we build a domain-specific language like traditional BI tools? Looker has LookML. dbt has its own modeling language. Do we go that route? Do we abandon notebooks altogether and build some custom execution format?
We wrote postmortems. Architecture decision records. Evaluation frameworks comparing every option. I won't pretend this was some clean decisive moment, it was messy and it took a long time. But the answer we arrived at changed the trajectory of the company.
We're not choosing between notebooks and DSLs.
The notebook IS a DSL compiler.
What that means: the AI works within the notebook environment to generate domain-specific analytical interfaces. The notebook is the compilation target, the engine room. Users never need to see it if they don't want to. What they see are boards, rendered outputs with controls that speak their business language. A sales team sees revenue filters and pipeline charts. A finance team sees margin analysis and cohort breakdowns. Underneath, it's all notebook cells. The notebook is the engine, not the interface.
What We Actually Built
Let me get specific because the details matter here.
Reactive Execution
Our notebook has a dependency graph. When you define a variable in Cell 1 and use it in Cell 3, the notebook knows. When Cell 1 changes, Cell 3 re-executes automatically. No manual re-running. No stale outputs.
It behaves like a spreadsheet, you change one thing and everything that depends on it updates. This is the single biggest difference from Jupyter and it changes everything about how the product feels.
When a business user moves a date slider, every chart, every metric, every summary that depends on that date range updates in real time. Nothing goes stale. Nothing falls out of sync. The notebook can't lie to you because the dependency graph won't let it.
Pure Python Files
Our notebooks are .py files. Not JSON. Not .ipynb. Python.
You can run them as scripts from a terminal. You can review them in any git diff tool and see exactly what changed. You can import them. You can test them.
Fuck the serialization issues of .ipynb.
A notebook should be code, and code should be a notebook. We use cell decorators to mark cell boundaries so the file is simultaneously a valid Python script and a structured notebook.
A Custom Kernel
We built our own kernel because Jupyter's protocol couldn't support what we needed at a fundamental level.
Jupyter's kernel speaks one language: "execute this string of code."
No concept of dependencies. Can't tell you that Cell B depends on Cell A. Can't register UI elements across cells. Can't do reactive re-execution because it doesn't know what to re-execute.
Our kernel has a dependency graph baked in. It has a UI element registry so interactive components, sliders, filters, dropdowns, can drive computation reactively across the entire notebook. Direct Python execution in a controlled namespace, not the string-serialization approach Jupyter uses.
And it manages all code execution centrally, so we know exactly what's running, what depends on what, and what needs to update when something changes.
Everything Is the Notebook
This is the part i think is underappreciated even by people who understand everything else.
In Querio the notebook isn't just where data analysis happens. It's the runtime for the entire product.
Boards and layouts? Notebook cells rearranged visually with a layout configuration on top. When you "create a board," you're selecting which cells to display and how to arrange them. The board refreshes on a schedule because the notebook runs on a cron. Same cells, same code, same outputs, different presentation layer.
Saved context files? Notebooks. When a data team saves reusable definitions, metrics, or business logic into Querio's context layer, those are .py notebook files that the AI can import and reference.
API endpoints? They execute in the notebook. When you expose an analysis as an API, the request triggers notebook execution and returns the output. Same code path, same runtime.
Scheduled reports? A cron job runs the notebook. The outputs get packaged and emailed. Same cells that power the board generate the report.
[IMAGE: Central "Notebook (.py)" icon with spokes radiating to: "Board" (cells as a dashboard), "API" (cells returning JSON), "Scheduled Report" (cells on a cron, emailed), "Context Layer" (cells as reusable definitions), "AI Chat" (cells generated by the agent). One notebook, many surfaces.]
Because everything runs on the same substrate, we don't have to build separate systems for dashboards, APIs, reports, and embedded analytics.
Build it once in the notebook, distribute it everywhere.
One source of truth, many interfaces.
Why This Makes Querio Good
When the AI generates an analysis, it produces a notebook. A persistent, versioned, editable .py file that holds the full chain of logic: the SQL query, the Python transformation, the visualization, the explanation.
Your data team can open it, read every line, verify the logic, improve it. There's no black box. The AI's work is as transparent as any analyst's work would be.
When a business user asks a question through our chat, the AI generates a notebook behind the scenes and renders the output as a board.
User sees a clean, interactive answer. Data team sees the code. Both are looking at the same source of truth.
When the data team improves the notebook, the business user's board gets better automatically.
One Change Propagates Everywhere
When a metric definition changes, it propagates. Across notebooks, across boards, across the platform. You change a definition once and every downstream artifact updates because the dependency graph handles it.
No more "which dashboard has the old formula" conversations.
The Notebook as Institutional Memory
When a data team member builds a deep analysis manually, that work doesn't die on their laptop.
It becomes a .py file the AI can import and build on, using the same logic to answer future questions from anyone in the organization.
The notebook is the unit of institutional knowledge.
The Future: Data Apps and Beyond
This is where this decision really starts to compound.
A reactive notebook with interactive UI elements is, structurally, an application runtime.
Think about what Retool does, it lets you build internal tools by wiring together UI components, data queries, and logic. Our notebook already does that. A date picker filtering a SQL query feeding a chart driving a summary metric, all reactive, all connected.
That's an app.
The difference is ours is generated by AI and backed by the full expressiveness of Python. You're not dragging and dropping in a visual builder and hitting the walls of what the builder supports.
You're describing what you need and the system compiles it into a reactive notebook that functions as an application.
Today that shows up as boards and reports.
Tomorrow it's embedded analytics inside your product, running on the same notebook, using the same context layer, governed by the same permissions. Automated workflows that execute on a cron and alert when something changes. Interactive operational tools your customer success team uses daily.
All of it running on the same notebook substrate.
Authored once, distributed everywhere.
The Flywheel
The flywheel is simple:
Data teams do real work in notebooks.
That work becomes reusable logic and trusted context.
The AI uses that context to serve the whole organization.
The more the data team invests, the smarter the platform gets, the more surfaces it can power.
Each notebook cell that gets written makes every future analysis more reliable, every future board more accurate, every future AI answer more trustworthy.
We didn't build a notebook because we love notebooks.
We built one because it's the only architecture that lets an AI agent and a human team co-author analytics that are transparent, reactive, reusable, and extensible into applications.
The notebook was dead.
We brought it back to life.
If you want to see what this actually feels like, reach out to me at rami@querio.ai or book a demo at querio.ai.
Written by

