Skip to content
Announcement

Observable SQL Is Replacing ORMs in New Codebases

Teams are ditching ORMs for observable SQL layers that expose query performance in real time. Here's why — and how to make the shift without chaos.

April 17, 2026TechMeetups.io10 min read
Observable SQL Is Replacing ORMs in New Codebases

The ORM debate has been cycling for two decades. Every few years someone writes "ORMs are bad" and someone else writes "ORMs are fine, you're using them wrong." Both sides make valid points. Neither side wins. The cycle repeats.

But something different is happening in 2026. Teams aren't just complaining about ORMs — they're replacing them with a category of tooling that didn't quite exist three years ago. Call it observable SQL: lightweight query layers that keep you close to actual SQL while giving you the type safety, migration tooling, and — critically — the runtime observability that ORMs never prioritized. And it's not just early adopters. A growing number of production codebases are being built this way from scratch, and some established teams are migrating mid-stream.

This isn't an ideology shift. It's a tooling shift. The tools finally caught up to what senior backend engineers always wanted.

What "Observable SQL" Actually Means

Let's be precise, because the term is loose. Observable SQL isn't a single product. It's a pattern — a convergence of three things:

1. Type-safe query builders that generate SQL you can read and predict (think Drizzle, Kysely, PgTyped, or the newer wave of Rust-based query compilers)

2. Compile-time or build-time SQL validation against your actual database schema, not an abstraction of it

3. Built-in query telemetry — execution time, row counts, query plans, and connection pool metrics emitted as structured traces, not buried in debug logs

The key difference from a traditional ORM: there's no object-relational mapping layer generating SQL behind an abstraction you can't see. You write something close to SQL (or literal SQL with type annotations), the tooling validates it, and when it runs in production, you get first-class observability data without bolting on an APM afterthought.

Why Now?

Three converging pressures made this inevitable:

  • OpenTelemetry matured. OTel's database instrumentation specs stabilized over the past year. Query builders that emit OTel spans natively can plug into any observability stack — Grafana, Honeycomb, Datadog, whatever. This used to require custom middleware. Now it's a config flag.
  • TypeScript's type system got powerful enough. Template literal types and conditional types made it possible to parse SQL strings at compile time and infer result types. This was a party trick in 2023. By 2025 it was production-grade.
  • The N+1 problem got worse, not better. As teams adopted more granular service boundaries and edge-rendered pages, the ORM's tendency to generate unpredictable queries became more expensive. One hidden N+1 in an edge function means hundreds of cold database round-trips per request.

What Teams Are Actually Doing Differently

If you browse engineering jobs on any major board right now, you'll notice a pattern: backend roles increasingly list Drizzle, Kysely, or "raw SQL with type safety" as preferred skills. ORM expertise (Prisma, TypeORM, Sequelize) still shows up, but it's migrating toward maintenance-of-existing-systems roles rather than greenfield work.

Here's what the shift looks like in practice:

1. Queries Are Visible in Code Review

With an ORM, a code review might show:

```typescript

const users = await User.findAll({

where: { status: 'active' },

include: [{ model: Order, where: { total: { [Op.gt]: 100 } } }]

});

```

The reviewer has to mentally compile this into SQL to evaluate it. With an observable SQL approach:

```typescript

const users = await db

.select({ id: users.id, name: users.name, orderTotal: orders.total })

.from(users)

.innerJoin(orders, eq(users.id, orders.userId))

.where(and(eq(users.status, 'active'), gt(orders.total, 100)));

```

The SQL is right there. The reviewer can reason about indexes, join order, and selected columns without decoding an abstraction layer. This sounds minor. In practice, it cuts code review time for database-touching PRs significantly.

2. Query Performance Is a First-Class Metric

The "observable" part isn't marketing. Teams using these tools are setting up dashboards that show:

MetricSourceAlert Threshold
p95 query execution timeOTel span duration> 200ms
Queries per requestSpan count per trace> 10 (possible N+1)
Connection pool saturationPool metrics export> 80% utilization
Rows scanned vs. returnedQuery plan annotationsRatio > 100:1

This data was always theoretically available, but ORMs made it hard to correlate "this slow trace" with "this specific generated query" because the abstraction layer scrambled the relationship between your code and the SQL that actually ran.

3. Migrations Are Schema-Driven, Not Model-Driven

ORM migrations derive from model definitions. You change a model, the ORM diffs it against the database, and generates a migration. This works until it doesn't — and when it doesn't, you're debugging auto-generated SQL that may not match your mental model.

The observable SQL pattern flips this: you write migrations as SQL (or use a schema-diffing tool like `pgroll` or `atlas`), and your query types are generated from the actual database schema. The source of truth is the database, not the application code. This eliminates an entire class of drift bugs.

The Honest Tradeoffs

I'm not going to pretend this is all upside. There are real costs.

You write more code. ORMs are concise for simple CRUD. If your app is mostly basic create-read-update-delete with simple relations, an ORM will ship features faster. Observable SQL shines when queries get complex or when performance matters at scale.

You need SQL literacy on the team. This is a feature if you're a senior engineer. It's a hiring constraint if you're building a team. Some junior developers have never written a JOIN by hand. The ORM abstraction, for better or worse, lowered the barrier to working with relational data.

Tooling is younger. Prisma has had years to build migration tooling, studio UIs, and edge deployment support. Drizzle and Kysely are catching up fast but have rougher edges. You'll hit GitHub issues that don't have answers yet.

You lose lazy loading. ORMs like Hibernate and ActiveRecord let you traverse relations without explicit joins. This is the source of N+1 problems, but it's also genuinely convenient for rapid prototyping. Giving it up means being explicit about every data access pattern.

When to Use What

Here's a decision framework that's actually useful:

ScenarioRecommendation
Greenfield API with complex queriesObservable SQL (Drizzle, Kysely, PgTyped)
CRUD-heavy admin tool or internal appORM is fine — Prisma, Sequelize, whatever ships fastest
Existing ORM codebase with perf issuesAdd OTel instrumentation first, then migrate hot paths
Team with low SQL experienceORM with mandatory query logging + review
Edge-deployed functions hitting a databaseObservable SQL — you need predictable, minimal queries

How to Start the Migration Without Breaking Everything

If you're on an ORM today and this resonates, don't rewrite. Migrate incrementally.

Step 1: Instrument What You Have

Before changing any query patterns, add OpenTelemetry instrumentation to your existing ORM. Most ORMs have middleware or plugin hooks for this. Get a baseline: which queries are slow? Which endpoints generate the most queries per request? You can't improve what you can't see.

Step 2: Identify Your Top 10 Painful Queries

Sort by p95 latency or by query count per request. These are your migration candidates. Don't touch the simple CRUD — it's not where the pain is.

Step 3: Run Both Side by Side

Most observable SQL tools can coexist with an ORM in the same codebase. They just need a database connection. Rewrite your painful queries using the new tool, deploy behind a feature flag, compare telemetry. This is a weekend project, not a quarterly initiative.

Step 4: Make It the Default for New Code

Once you've validated the pattern on a few hot paths, update your team's conventions: new queries use the observable SQL layer, existing ORM code gets migrated opportunistically. Set a lint rule if you want to enforce it.

If you're looking to discuss migration strategies with other backend engineers, it's worth checking out what's happening at developer meetups near you. These conversations are happening in real-time at local engineering nights across the country.

The Bigger Shift: Dev Tooling That Prioritizes Observability

Observable SQL is part of a broader trend: developer tools that treat production visibility as a first-class concern, not a bolt-on. We're seeing the same pattern in feature flag systems (flags as structured events), in build tools (build traces as OTel spans), and in CI pipelines (test execution as observable workflows).

The common thread: the boundary between "development" and "operations" keeps dissolving, and the tools that win are the ones that acknowledge this. If you can't see how your code behaves in production from the artifact you wrote in your editor, the abstraction is hiding too much.

ORMs were designed in an era when the database was someone else's problem — a DBA's domain, separated from application code by an abstraction layer. In 2026, the engineer who writes the query is usually the same person debugging it at 2 AM. The tools should reflect that reality.

Concrete Takeaways

If you leave with two things:

1. Add OTel instrumentation to your database layer this week. Whether you use an ORM or raw SQL, you should be able to answer "what are my slowest queries and which code paths trigger them?" If you can't, that's your first priority — before any architectural change.

2. Try rewriting one complex query path with a type-safe query builder. Pick something with a JOIN or a subquery. Compare the developer experience: readability in code review, type inference in your editor, and the observability data you get for free. Let the experience inform your opinion, not the discourse.

FAQ

Is observable SQL just writing raw SQL with extra steps?

Not exactly. Raw SQL gives you no type safety, no compile-time validation, and no structured telemetry. Observable SQL tools validate your queries against the actual schema at build time, infer return types automatically, and emit performance data as structured traces. It's closer to SQL than an ORM, but it's not unassisted.

Should I migrate my existing Prisma/TypeORM codebase?

Probably not wholesale. The ROI is highest on complex queries and performance-critical paths. Simple CRUD operations work fine in any ORM. Start by instrumenting what you have, identify the pain points, and migrate those surgically. A mixed codebase is fine — purity is not the goal.

What about Prisma's recent improvements to query visibility?

Prisma has made real progress — their tracing integration and query engine metrics have improved substantially. If you're already on Prisma and it works for your scale, adding their OTel integration might be enough. The shift to observable SQL is most compelling for teams starting new projects or those hitting limits that the ORM's generated queries can't solve. Use what works. Swap what doesn't.

Find Your Community

Database patterns, ORM debates, and observability practices are the kind of topics that benefit enormously from talking to people who've actually done the migration. If you're working through these decisions, explore tech events in your city or find developer meetups near you — the backend and infrastructure tracks at local meetups are where these real-world stories get shared. And if you're looking for teams that are already building this way, browse open tech jobs to see who's hiring for this stack.

industry-newsnationalengineeringsqlormsobservabilitybackenddeveloper-experiencearchitecturedatabases

Discover Denver Tech Communities

Browse active meetups and upcoming events