We’ve shipped native support for SQL Server in Materialize.

That means you can now connect Materialize directly to your SQL Server instance and build views that stay perfectly in sync with your production data. No Kafka. No Debezium. No polling. Just a direct connection that continuously reflects every committed change.

You Can’t Build Operational Systems by Querying the Primary

The first instinct is always to just write the query.

You want to know how many orders came in over the last 15 minutes. Or which users are still active but haven’t converted. Or what the running total is for an open invoice. You write the SQL, it runs, but it’s slow.

Not because your query is bad, but because your database is busy. The kinds of queries that involve joins, filters, aggregates and touch a lot of rows. If you’re running them directly against the OLTP system, you’re putting pressure on the same infrastructure that’s handling customer traffic.

So you reach for a read replica. That’s supposed to help as it offloads traffic from the primary. But it doesn’t change what the system is. You’re still querying an OLTP engine, just a copy of it. And OLTP systems aren’t designed to scan millions of rows, join across tables, or compute aggregates over rolling windows. You can throw more replicas at the problem, but the queries are still slow. You’re scaling the wrong thing. You end up with more infrastructure, more cost, and the same bottleneck.

At this point, you’re stuck. The logic you need is expensive. The system you’re in can’t compute it without tradeoffs. And the real problem is that you’re asking your database not just to store your data, but to continuously compute on it.

Indexed Views Were the Attempt. They Aren’t the Answer.

SQL Server tried to solve this with indexed views. Persist the result of a query to disk. Keep it updated as writes come in. Let the optimizer use it to accelerate queries.

It almost works.

Until you realize how limited the model is. You can’t use outer joins, or self joins. No distinct on, or union. You can’t use window functions or common table expressions. And you’re forced to rewrite your query using special aggregates like COUNT_BIG.

And even if you manage all that, writes still suffer. Every insert, update, or delete on a base table must synchronously update the indexed view before the transaction can commit. Lock contention goes up. Throughput goes down.

And none of this helps if your logic spans multiple databases. Indexed views can’t cross those boundaries. If your model touches inventory in one place and fulfillment in another, you’re out of luck.

What We Built

Materialize now integrates natively with SQL Server by reading directly from its built-in Change Data Capture (CDC) stream. This unlocks something SQL Server was always quietly capable of—recording every change, with transactional precision—and turns it into the foundation for real-time, always-correct derived state.

Here’s how it works.

When you create a source in Materialize, we begin by taking a consistent snapshot of your tables—guaranteed by SQL Server’s snapshot isolation. From there, we tail CDC: a reliable, append-only stream of all committed changes, emitted in the order they were applied. Each row in CDC includes a log sequence number (LSN), marking exactly when and how it was written. That gives us everything we need to compute downstream state.

Materialize ingests those changes as they happen. We track LSNs internally, apply changes in commit order, and group them by transaction. If one transaction updates ten rows across three tables, Materialize waits until all ten have landed—then applies them as a unit. That consistency guarantee is built in, not layered on.

What makes this powerful is what happens next.

Each SQL view you define in Materialize—whether it’s a complex join, a windowed aggregation, or a filter over streaming data—is compiled into an incremental dataflow. As new changes arrive, we update only what’s affected. There’s no reprocessing. No polling. No batch delay. Just a live view of your logic, kept fresh by changes happening upstream.

This isn’t an interface for change data. It’s a system for maintaining the results of your most important logic. SQL Server handles transactions. Materialize handles everything that comes after.

This Is the Right System for Operational Data Products

Operational data products aren’t dashboards. They’re not metrics. They’re living models of how your business is changing: which customers are active, which orders are stuck, which regions are falling behind forecast.

They power systems: notification engines, fraud checks, inventory routing, in-app personalization.

And they only work if they’re current. If the view of the world they expose reflects what’s happening in the source systems now, not five minutes ago, or once the next job runs.

Materialize turns these models into first-class, queryable views—expressed in SQL, maintained incrementally, and made accessible over the wire like any other database table. They’re not recomputed. They’re updated. They’re not close enough. They’re correct.

How This Changes Your Stack

With Materialize, you don’t need a pipeline. You just write the logic.

sql
CREATE MATERIALIZED VIEW high_intent_users_missing_checkout AS
SELECT
    s.user_id,
    MAX(s.session_start) AS last_session,
    COUNT(a.action) FILTER (WHERE a.action = 'add_to_cart') AS cart_adds,
    COUNT(a.action) FILTER (WHERE a.action = 'begin_checkout') AS checkouts_started,
    COUNT(a.action) FILTER (WHERE a.action = 'purchase') AS purchases,
    bool_or(a.action = 'purchase') AS completed_purchase
FROM
    user_sessions s
LEFT JOIN
    user_actions a
    ON s.session_id = a.session_id
WHERE
    s.session_start > mz_now() - interval '10 minutes'
GROUP BY
    s.user_id
HAVING
    COUNT(a.action) FILTER (WHERE a.action = 'add_to_cart') > 1
    AND bool_or(a.action = 'purchase') = false;

Every time a user starts a new session, or clicks “add to cart,” or checks out, this view updates immediately and consistently.

Views like this are what operational data products are made of. They model behavior of live systems. They expose what’s happening now. And because they’re written in SQL, they’re composable, inspectable, and ready to power everything from backend services or operational dashboards.

Available Now

This is the system SQL Server never had. The one where you can compute live, maintain operational data products incrementally, and do it all without compromising your primary workload.

We’re excited to bring the power of Materialize directly to the SQL Server ecosystem. Start your free trial or join us on Slack — we’d love to hear what you’re building!

Get Started with Materialize