Observable SQL Is Quietly Replacing REST for Internal Tools
Teams are skipping REST APIs entirely for internal tools, writing observable SQL queries that stream live results to UIs. Here's why it works and where it breaks.
Your backend team just spent three sprints building a CRUD API for an internal dashboard that six people use. The API has pagination, filtering, sorting, auth middleware, error handling, rate limiting, and OpenAPI docs. It's beautiful engineering. It's also a mass of code that exists solely to shuttle rows from Postgres to a React table.
Something has shifted in how teams build internal tools in 2026, and it's not another no-code platform or AI-generated CRUD layer. A growing number of engineering orgs — from 20-person startups to mid-size companies with hundreds of engineers — are exposing observable SQL queries directly to their frontends for internal tooling. No REST. No GraphQL. No BFF. Just a SQL query that streams results to the browser and updates when the underlying data changes.
It sounds reckless. It's actually working.
What Observable SQL Actually Means
Let's be precise, because "SQL in the frontend" triggers justified alarm bells.
Observable SQL doesn't mean your React app is running `SELECT *` against your production database. The pattern looks like this:
1. A developer writes a parameterized SQL query in a server-side definition file
2. The query is registered with a reactive query layer (more on the tools later)
3. The frontend subscribes to that query with specific parameters
4. Results stream to the client over WebSockets or server-sent events
5. When underlying data changes, the query re-executes and pushes diffs
The key insight: the SQL query is the API contract. There's no controller, no service layer, no DTO mapping, no serialization logic. The query defines what data is available, the parameters define the access pattern, and the reactive layer handles the plumbing.
This is not new computer science. Materialized views, change data capture, and reactive queries have existed for years. What's new is the tooling convergence that makes this pattern practical for small teams building internal software.
The Stack Making This Possible
Several tools have matured enough in the past year to make this pattern viable:
- Electric SQL has moved well beyond its SQLite sync origins. Its server-side component now supports streaming partial replication from Postgres with row-level security predicates.
- LiveStore (which grew out of the local-first movement) provides a reactive query layer that works with multiple backend databases and handles incremental result diffing.
- Materialize and its open-source alternatives have made incremental view maintenance accessible without requiring a PhD in stream processing.
- GROQ-style query languages in tools like Sanity have normalized the idea of subscribable queries, making the pattern feel less alien to frontend developers.
The typical implementation at most teams using this pattern involves Postgres as the source of truth, a CDC (change data capture) pipeline, a reactive query engine, and a thin WebSocket gateway. The frontend subscribes to named queries with parameters.
A Concrete Example
Say you're building an internal order management tool. In the REST world, you'd build:
- `GET /api/orders?status=pending&page=1&limit=50`
- `GET /api/orders/:id`
- `PATCH /api/orders/:id`
- Maybe `GET /api/orders/stats` for a dashboard widget
- WebSocket or polling for real-time updates
In the observable SQL pattern, you'd write:
```sql
-- queries/pending_orders.sql
SELECT o.id, o.status, o.total, c.name as customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.status = :status
ORDER BY o.created_at DESC
LIMIT :limit OFFSET :offset
```
The frontend subscribes:
```typescript
const orders = useQuery('pending_orders', {
status: 'pending',
limit: 50,
offset: 0
});
```
When an order status changes — from any source, not just your UI — the query re-evaluates and the component updates. No polling. No cache invalidation. No optimistic updates that might diverge from reality.
Write operations still go through a proper API layer (mutations need validation, business logic, and audit trails). But the read path, which is 80-90% of what internal tools actually do, collapses from hundreds of lines of API code to a SQL file and a hook.
Why Teams Are Actually Adopting This
The pattern isn't winning on technical elegance. It's winning on time to ship.
Internal tools exist in a weird liminal space. They need to be functional and reliable, but they rarely justify the engineering investment of a customer-facing product. Most internal tools are built grudgingly, maintained reluctantly, and eventually abandoned for a spreadsheet.
Observable SQL changes the economics:
| Dimension | REST API Approach | Observable SQL Approach |
|---|---|---|
| Time to first query | Days (routes, controllers, serializers) | Hours (write SQL, register, subscribe) |
| Real-time updates | Additional WebSocket infrastructure | Built-in |
| Schema changes | Update API, DTOs, client types | Update SQL query |
| New filter/sort need | New endpoint or parameter handling | Modify SQL |
| Data freshness | Polling interval or manual refresh | Live |
| Lines of backend code | Hundreds per resource | Tens per query |
A staff engineer at a logistics company described it to me at a meetup last month: "We cut our internal tools backlog by about 60% in a quarter. Not because we worked faster, but because each tool needed so much less code."
The other underrated advantage: SQL is the lingua franca. Your data analysts already write it. Your DBAs review it. Your product managers can read it (mostly). When the API contract is a SQL query, the surface area for miscommunication shrinks dramatically. Compare that to debugging why the REST endpoint returns a different shape than the frontend expects, then discovering it's a serialization issue in a DTO mapper four layers deep.
Where This Breaks Down
Let's be honest about the sharp edges, because there are plenty.
Security Is Harder to Reason About
With REST, your authorization logic lives in middleware and service layers. You can see it, test it, audit it. With observable SQL, row-level security becomes critical infrastructure. You're relying on database-level RLS policies or the reactive layer's permission model to ensure users only see data they should.
This is solvable — Postgres RLS is mature, and most reactive query tools add their own permission layers — but it requires a different security mindset. Most teams implementing this pattern report that getting the security model right takes more upfront design than the REST equivalent, even if the total code is less.
Write Operations Still Need APIs
Observable SQL handles reads beautifully. Writes are a different story. You still need validation, authorization, business logic, side effects (sending emails, updating caches, triggering workflows), and audit logging. Trying to make writes reactive in the same way leads to pain.
The pattern that's emerging: observable SQL for reads, traditional API endpoints (often simple RPC-style) for writes. This hybrid approach captures most of the productivity gains while keeping mutation logic explicit and testable.
Not Every Query Is Efficiently Observable
A query that joins six tables with complex aggregations doesn't re-evaluate cheaply when one row changes. Incremental view maintenance has limits. Teams learning this pattern often hit a wall when they try to make complex analytical queries observable and find the reactive layer consuming significant database resources.
The practical rule of thumb: if the query would be expensive as a materialized view, it's probably expensive as an observable query. Use traditional request/response for complex analytics and save observability for the operational queries that benefit from liveness.
It's Internal-Only (For Now)
No one serious is suggesting this pattern for customer-facing APIs. The security surface area, the need for rate limiting, versioning, and backward compatibility — these all favor traditional API design. Observable SQL works for internal tools because you control both sides of the wire and your users are colleagues, not adversaries.
Actionable Takeaways
If you're curious about trying this pattern, here's where to start:
Start with one read-heavy internal tool. Pick something simple — a dashboard, a queue viewer, an admin search page. Implement the read path with observable SQL while keeping writes on your existing API. Measure how long it takes compared to your usual approach. Most teams report the gap is large enough to justify further investment.
Invest in your Postgres RLS policies before anything else. The security model is the foundation. If you don't have row-level security policies that you trust, don't pipe queries to frontends. Spend the time here first. Write tests that verify unauthorized users cannot access rows through any registered query. This is non-negotiable.
Don't try to eliminate REST across the board. The observable SQL pattern is a tool for a specific context: internal tools with read-heavy access patterns where data freshness matters. It complements your existing API layer. Teams that try to make it their entire architecture end up fighting the pattern instead of benefiting from it.
The Bigger Picture
Observable SQL is part of a broader trend: the collapsing of accidental complexity in internal tooling. Between this pattern, the maturation of local-first architectures, and AI-assisted code generation that handles CRUD boilerplate, the cost of building internal tools is dropping fast.
This matters because internal tools are where developer experience and operational efficiency intersect. A team that can ship an internal tool in a day instead of a sprint is a team that spends more time on customer-facing work. If you're a platform engineering team wondering where to invest next, making internal tool development faster might be higher leverage than you think.
If you want to see how other teams in your area are approaching these architectural decisions, it's worth checking out what's happening at local meetups. The best conversations I've had about this pattern happened at in-person events where people could whiteboard their specific setups and constraints. You can find developer meetups near you or explore tech events in your city to see what's happening locally.
FAQ
Is observable SQL safe for production internal tools?
Yes, with caveats. The SQL queries are server-defined (not user-submitted), parameterized, and executed through a controlled reactive layer. Combined with Postgres row-level security and proper authentication on the WebSocket connection, the security posture is comparable to a well-built REST API. The key is that the SQL is pre-registered and parameterized — users supply parameter values, not arbitrary queries.
Does this replace GraphQL for internal tools?
For many teams, yes. GraphQL solved the over-fetching and under-fetching problem for client-server communication, but it introduced its own complexity: schema design, resolver implementation, N+1 queries, and caching. Observable SQL sidesteps most of this for internal tools because you control both client and server. You write the exact query you need, and the reactive layer handles delivery. If you're building a public API for third-party consumers, GraphQL still has a role.
What databases work with this pattern?
Postgres is the most common because of its mature logical replication and RLS support. Most reactive query tools use Postgres's WAL (write-ahead log) for change detection. MySQL and its variants can work with tools that use binlog-based CDC, but the ecosystem is less mature. SQLite-based local-first tools like Electric SQL offer a different flavor of the same idea. If you're on a managed database service, check that logical replication is enabled — it's not always the default.
Find Your Community
Architectural patterns like this spread fastest through practitioner communities — people sharing what actually worked (and what didn't) at their company. Whether you're exploring observable SQL, building platform engineering practices, or just want to talk shop with other backend engineers, local tech meetups are where these conversations happen. Explore meetups in your city to find your people, or browse open tech jobs if you're looking for teams that are already pushing these boundaries.