---
title: "Database Migration Query Merger"
description: "The Migrate -> MergeQueries execution flow represents the end-to-end lifecycle of schema migration execution within Drizzle ORM's PostgreSQL and Netlify Database adapters. When a user triggers data..."
last_updated: "2026-10-12T08:14:00.757955+00:00"
canonical_url: "https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/technical/how-it-works/database-migration-query-merger"
---

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [drizzle-orm/src/netlify-db/migrator.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts)
- [drizzle-orm/src/node-postgres/migrator.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/node-postgres/migrator.ts)
- [drizzle-orm/src/pg-core/dialect.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts)
- [drizzle-orm/src/pg-core/session.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/session.ts)
- [drizzle-orm/src/sql/sql.ts](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts)
</details>

## Overview

### Introduction

The **Migrate -> MergeQueries** execution flow represents the end-to-end lifecycle of schema migration execution within Drizzle ORM's PostgreSQL and Netlify Database adapters. When a user triggers database migrations, migration files are parsed, converted into executable `SQL` templates, compiled into database-ready query strings with parameterized values, and finally merged into cohesive query batches executed via a database session transaction.

Sources: [drizzle-orm/src/netlify-db/migrator.ts:8-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts#L8-L18), [drizzle-orm/src/node-postgres/migrator.ts:5-11](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/node-postgres/migrator.ts#L5-L11), [drizzle-orm/src/pg-core/dialect.ts:73-112](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L73-L112)

---

## Step-by-Step Execution Trace

### Step 1: Netlify-DB Migration Entrypoint

The migration process can initiate from the Netlify Database adapter's `migrate` function. It checks whether the provided database instance is an instance of `NodePgDatabase`. If so, it delegates execution directly to the Node-Postgres migrator; otherwise, it reads migration files from disk/configuration and passes them to the underlying database session dialect.

Sources: [drizzle-orm/src/netlify-db/migrator.ts:8-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts#L8-L18)

### Step 2: Node-Postgres Migration Entrypoint

For standard Node-Postgres setups, the `migrate` function loads the migration metadata using `readMigrationFiles(config)` and invokes `db.dialect.migrate(...)` with the parsed migrations, database session, and configuration.

Sources: [drizzle-orm/src/node-postgres/migrator.ts:5-11](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/node-postgres/migrator.ts#L5-L11)

### Step 3: PostgreSQL Dialect Migration Handler

The `PgDialect.migrate` method sets up the migrations tracking table (`__drizzle_migrations`), checks existing records in the database, opens a transaction, and loops through unapplied migration scripts, executing individual statements inside a transaction block.

Sources: [drizzle-orm/src/pg-core/dialect.ts:73-112](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L73-L112)

### Step 4: Session Execution & Query Preparation

When `tx.execute(...)` is called with an `SQL` template object, the `PgSession` wraps the operation inside active telemetry spans, turning the raw `SQL` object into a prepared query via `this.dialect.sqlToQuery(query)`.

Sources: [drizzle-orm/src/pg-core/session.ts:190-207](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/session.ts#L190-L207)

### Step 5: Dialect SQL-to-Query Conversion

`PgDialect.sqlToQuery` acts as a bridge, invoking `sql.toQuery(...)` with dialect-specific configurations such as custom casing rules, parameter escaping, and typing functions.

Sources: [drizzle-orm/src/pg-core/dialect.ts:609-618](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L609-L618)

### Step 6: SQL Object Query Compilation

`SQL.toQuery` initiates an active OpenTelemetry tracing span (`drizzle.buildSQL`) and invokes `buildQueryFromSourceParams` over the internal query chunks to compile textual SQL and parameter lists.

Sources: [drizzle-orm/src/sql/sql.ts:137-146](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L137-L146)

### Step 7: Building Query from Source Parameters

`buildQueryFromSourceParams` iterates through every `SQLChunk` inside the expression tree—handling strings, names, identifiers, tables, parameters, and nested `SQL` objects—producing a list of partial `QueryWithTypings` objects.

Sources: [drizzle-orm/src/sql/sql.ts:148-300](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L148-L300)

### Step 8: Merging Queries

`mergeQueries` aggregates an array of `QueryWithTypings` chunks into a single, unified `QueryWithTypings` result object by concatenating SQL strings, accumulating parameter arrays, and merging type definitions.

Sources: [drizzle-orm/src/sql/sql.ts:74-87](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L74-L87)

---

## Architecture Diagrams

### Sequence Diagram

```mermaid
sequenceDiagram
    autonumber
    participant NetlifyMigrator as netlify-db/migrator.ts
    participant NodePgMigrator as node-postgres/migrator.ts
    participant PgDialect as pg-core/dialect.ts
    participant PgSession as pg-core/session.ts
    participant SQLObj as sql/sql.ts (SQL)

    alt Netlify DB (Non-NodePg)
        NetlifyMigrator->>PgDialect: migrate(migrations, session, config)
    else Node-Postgres / NodePg fallback
        NetlifyMigrator->>NodePgMigrator: migrate(db, config)
        NodePgMigrator->>PgDialect: migrate(migrations, session, config)
    end

    loop For each unapplied migration statement
        PgDialect->>PgSession: tx.execute(sql)
        PgSession->>PgDialect: sqlToQuery(query)
        PgDialect->>SQLObj: sql.toQuery(config)
        SQLObj->>SQLObj: buildQueryFromSourceParams(chunks, config)
        SQLObj->>SQLObj: mergeQueries(queries)
        SQLObj-->>PgDialect: QueryWithTypings
        PgDialect-->>PgSession: Executed query result
    end
```

Sources: [drizzle-orm/src/netlify-db/migrator.ts:8-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts#L8-L18), [drizzle-orm/src/node-postgres/migrator.ts:5-11](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/node-postgres/migrator.ts#L5-L11), [drizzle-orm/src/pg-core/dialect.ts:73-112](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L73-L112), [drizzle-orm/src/pg-core/session.ts:190-207](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/session.ts#L190-L207), [drizzle-orm/src/sql/sql.ts:74-146](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L74-L146)

### Flowchart

```mermaid
flowchart TD
    A[Migrate Entrypoint] --> B{Is NodePgDatabase?}
    B -- Yes --> C[NodePg Migrate]
    B -- No --> D[Read Migration Files]
    C --> D
    D --> E[PgDialect.migrate]
    E --> F[Execute Migration Statements]
    F --> G[PgSession.execute]
    G --> H[PgDialect.sqlToQuery]
    H --> I[SQL.toQuery]
    I --> J[buildQueryFromSourceParams]
    J --> K[mergeQueries]
    K --> L[Database Transaction Execution]
```

Sources: [drizzle-orm/src/netlify-db/migrator.ts:8-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts#L8-L18), [drizzle-orm/src/node-postgres/migrator.ts:5-11](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/node-postgres/migrator.ts#L5-L11), [drizzle-orm/src/pg-core/dialect.ts:73-112](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L73-L112), [drizzle-orm/src/pg-core/session.ts:190-207](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/session.ts#L190-L207), [drizzle-orm/src/sql/sql.ts:74-146](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L74-L146)

---

## Key Observations

- **Cross-Module Boundaries:** The execution flow seamlessly traverses driver-specific migrators (`netlify-db`, `node-postgres`), core database dialects (`pg-core`), active session managers, and core SQL query construction primitives (`sql/sql.ts`).
- **Transaction Safety:** Migration scripts are executed sequentially inside a database transaction (`session.transaction`), ensuring that schema updates are atomic and rolling back if any statement fails.
- **Telemetry & Tracing:** OpenTelemetry spans (`drizzle.operation`, `drizzle.prepareQuery`, `drizzle.buildSQL`) wrap query preparation and execution phases to monitor performance overhead.

Sources: [drizzle-orm/src/netlify-db/migrator.ts:8-18](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/netlify-db/migrator.ts#L8-L18), [drizzle-orm/src/pg-core/dialect.ts:95-111](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/dialect.ts#L95-L111), [drizzle-orm/src/pg-core/session.ts:195-206](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/pg-core/session.ts#L195-L206), [drizzle-orm/src/sql/sql.ts:138-146](https://github.com/blade47/drizzle-orm/blob/48e5406027103a9fca6eb66417187c4a8b5c6aa3/drizzle-orm/src/sql/sql.ts#L138-L146)

## Sitemap

See the full [sitemap](https://www.doc0.dev/docs/e1b68fed-3c4e-4c95-b2ba-ebf050f78025/llms.txt) for all pages in this wiki.
