Skip to main content

Database branches

Beta

Lakebase Postgres (Autoscaling Beta) is the next version of Lakebase, available for evaluation only. For production workloads, use Lakebase Public Preview. See choosing between versions to understand which version is right for you.

Database branching in Lakebase lets you version, test, and evolve your data environment safely, similar to branching your code in Git. You can instantly create isolated, fully functional database branches for development, experimentation, or testing schema changes, without impacting production workloads.

By default, Lakebase creates two branches when you create a new project:

production (default branch)
└── development (child branch)

The production branch is your root branch, meant to house your application's production data. The development branch is a child of production, giving you a ready-to-use environment for building and testing. With branch reset, you can refresh development from production instantly to get the latest schema and data, without data seeding or teardown scripts.

You can create additional branches as needed to fit your workflow. For example, add a staging branch for pre-production testing, or create per-developer branches for complete isolation. Each branch operates independently—changes in a child never affect its parent.

How database branches work

Parent-child relationships

Every branch (except the root branch) has a parent. This creates a hierarchy:

production (root branch)
├── staging (child of production)
│ └── feature-test (child of staging)
└── development (child of production)
└── bugfix-branch (child of development)

This hierarchy gives you important isolation: changes you make to a child branch don't affect its parent, and changes to a parent don't automatically appear in children. When you need updated data from the parent, you can reset the child branch. You can also create branches from any point in the parent's history, which is useful for point-in-time recovery, testing against historical data, or compliance scenarios.

When you create a branch, you choose whether to initialize it from current data or from a specific point in time. See Create a branch for step-by-step instructions and details on each option.

Copy-on-write storage

Lakebase uses copy-on-write technology to make parent-child branching efficient. When you create a new branch, it inherits both the schema and data from its parent, but shares the underlying storage through pointers to the same data. Only when you modify data does Lakebase write new data. This means:

  • Your branches appear instantly; the size of your database has no impact on branch creation time
  • You only pay for data that actually changes between branches
  • Creating branches has no performance impact on your production workload
production branch          development branch (at creation)
┌─────────────────┐ ┌─────────────────┐
│ [Data A] │◄──────│ → Data A │ (shared)
│ [Data B] │◄──────│ → Data B │ (shared)
│ [Data C] │◄──────│ → Data C │ (shared)
└─────────────────┘ └─────────────────┘

After modifying data in development:
┌─────────────────┐ ┌─────────────────┐
│ [Data A] │◄──────│ → Data A │ (shared)
│ [Data B] │ │ [Data B'] │ (changed)
│ [Data C] │◄──────│ → Data C │ (shared)
└─────────────────┘ └─────────────────┘
Only changed data is stored separately

Working with branches

Branch reset

Branch reset instantly updates a child branch to match its parent's current state. This is useful when you want to refresh your development or staging branch with the latest production data. The operation completes instantly using copy-on-write technology, and your connection details remain the same.

Branch reset only works one direction (parent → child). To move changes from child to parent, use your standard migration tools to apply schema changes. See Reset a branch for detailed steps and scenarios.

Point-in-time recovery

You can create a branch from a specific point in time within your restore window, which is useful for recovering from data errors like accidental deletions, investigating past issues, or accessing historical data for auditing and compliance purposes. For example, if a critical table was dropped yesterday at 10:23 AM, you can create a branch set to 10:22 AM to extract the missing data. Similarly, you can create branches reflecting your database state at specific dates for financial reconciliations, regulatory audits, or forensic analysis. Unlike branch reset (which updates an existing branch), point-in-time recovery creates a new branch from historical data. See Point-in-time restore for details.

Special branch types

Default branch

When you create a Lakebase project, you automatically get two branches: production (the default branch) and development (a child of production). Both start empty, ready for your data. This setup gives you a safe workflow for getting started—test your schema changes in development, then run the same migrations against production when you're confident they work.

Your default branch never scales to zero, ensuring it remains available even when other branch computes scale down during idle periods.

Protected branches

Protected branches have safeguards to prevent accidental changes. They cannot be deleted or reset from their parent, and they're exempt from automatic archival due to inactivity. Protected branches also block project deletion while they exist, ensuring you can't accidentally remove critical infrastructure. Use protected branches for critical data like production. See Protected branches for details.

How branching impacts resource consumption

With database branches, you only pay for what you actually use.

Storage: You only pay for data that changes. If you create a development branch and modify 1GB of data in a 100GB database, you pay for approximately 1GB of storage, not 200GB. The unchanged 99GB is shared between branches.

Compute: Each branch has its own compute that you can scale independently. You pay only for active compute hours. Computes scale to zero when idle. This means a development branch you use occasionally costs far less than running a dedicated development server 24/7.

Default branch: Your default branch compute never scales to zero, ensuring your production workload remains available.

Branch strategies

Here are some common ways teams organize their branches:

Simple (individuals and small teams)

Use your default branches for all work:

production
└── development

Your development branch is where you build new features safely. You can make schema changes, add test data, and experiment without any risk to production. When you're ready, run your tested schema migrations against production (using your migration tool), then reset development to start the next feature with fresh data.

With staging

Add a staging branch for pre-production testing:

production
├── staging
└── development

If you need pre-production testing, maintain a staging branch that mirrors production data. Deploy your application there, run integration and performance tests against realistic data, and gain confidence before going live. Periodically reset staging from production to refresh your test data.

Per-developer branches

Each developer works in complete isolation:

production
└── development
├── dev-alice
├── dev-bob
└── dev-charlie

This pattern prevents developers from interfering with each other's work and allows everyone to test schema changes independently. Each developer can experiment with their own schema changes and data modifications without affecting others, then apply tested migrations to the shared development or production branch when ready.

Next steps