Skip to content

Git-Style Database Branching User Guide

Git-Style Database Branching User Guide

Overview

HeliosDB’s Git-style branching feature allows you to create instant, zero-copy snapshots of your database for development, testing, and debugging. Just like Git branches for code, you can create database branches for data.

Benefits

  • Instant branch creation (<1ms) with zero storage overhead
  • Test schema changes safely without affecting production
  • Debug production issues using time-travel queries
  • Develop features in isolation with real production data
  • Roll back to any point in time

Key Features

  • Copy-on-write (COW) semantics for storage efficiency
  • Branch creation at specific LSN or timestamp
  • Time-travel queries within branches
  • Automatic garbage collection
  • Full ACID guarantees per branch

Prerequisites

System Requirements

  • HeliosDB v3.2 or later
  • PostgreSQL-compatible client
  • Sufficient storage for branch divergence (typically 10-20% of main branch)

Required Permissions

-- User needs branch management permissions
GRANT EXECUTE ON FUNCTION heliosdb.create_branch TO developer_role;
GRANT EXECUTE ON FUNCTION heliosdb.delete_branch TO developer_role;
GRANT SELECT ON heliosdb.branches TO developer_role;

Step-by-Step Configuration

1. Enable Branch Support

Edit heliosdb.conf:

branching:
enabled: true
max_branches: 100
max_depth: 5
default_gc_retention_days: 30
snapshot_path: /var/lib/heliosdb/branches

Restart HeliosDB:

Terminal window
systemctl restart heliosdb

2. Verify Installation

-- Check if branching is enabled
SELECT heliosdb.branching_enabled();
-- List available branches
SELECT * FROM heliosdb.branches;

Expected output:

id | name | parent_id | creation_lsn | current_lsn | created_at | state | depth
------+------+-----------+--------------+-------------+------------+--------+-------
uuid | main | NULL | 0/0 | 0/5E2A | 2025-... | Active | 0

SQL Examples with Explanations

Creating Branches

Basic Branch Creation

-- Create a branch from the current HEAD of main
SELECT heliosdb.create_branch(
branch_name => 'feature-auth',
parent_branch => 'main'
);

Explanation: Creates an instant snapshot at the current LSN. All data from main is accessible in feature-auth without copying.

Time-Travel Branch

-- Create branch from a specific timestamp
SELECT heliosdb.create_branch(
branch_name => 'debug-session',
parent_branch => 'main',
from_timestamp => '2025-10-24 14:30:00'
);

Use Case: Debug production issues by recreating database state at the time of the incident.

LSN-Based Branch

-- Create branch from specific LSN
SELECT heliosdb.create_branch(
branch_name => 'rollback-test',
parent_branch => 'main',
from_lsn => '0/1234ABCD'
);

Use Case: Precise control for recovery or testing scenarios.

Working with Branches

Switch to a Branch

-- Set session context to work on a specific branch
SET heliosdb.current_branch = 'feature-auth';
-- All subsequent queries use this branch
INSERT INTO users (email, name) VALUES ('test@example.com', 'Test User');
-- Verify current branch
SHOW heliosdb.current_branch;

Query Multiple Branches

-- Compare data across branches
SELECT 'main' as branch, COUNT(*) FROM main.users
UNION ALL
SELECT 'feature-auth' as branch, COUNT(*) FROM feature_auth.users;

Time-Travel Queries

-- Query historical data within a branch
SELECT * FROM users
WHERE heliosdb.query_at_lsn('0/1234ABCD');
-- Query data as of specific timestamp
SELECT * FROM orders
WHERE heliosdb.query_at_timestamp('2025-10-24 12:00:00');

Branch Management

List All Branches

SELECT
name,
parent_id,
creation_lsn,
current_lsn,
EXTRACT(EPOCH FROM (now() - created_at))/3600 as age_hours,
state,
depth
FROM heliosdb.branches
ORDER BY created_at DESC;

Get Branch Statistics

SELECT heliosdb.branch_stats('feature-auth');

Output:

{
"name": "feature-auth",
"storage_mb": 2.4,
"delta_sstables": 3,
"memtable_size_mb": 0.5,
"depth": 1,
"divergence_percent": 10.2
}

Delete a Branch

-- Delete a branch (fails if it has children)
SELECT heliosdb.delete_branch('feature-auth');
-- Force delete (WARNING: deletes all child branches)
SELECT heliosdb.delete_branch('feature-auth', force => true);

Common Use Cases

Use Case 1: Schema Migration Testing

-- Create test branch
SELECT heliosdb.create_branch('schema-test', 'main');
SET heliosdb.current_branch = 'schema-test';
-- Test schema changes
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
CREATE INDEX idx_users_phone ON users(phone);
-- Run queries to validate
SELECT COUNT(*) FROM users WHERE phone IS NOT NULL;
-- If successful, apply to main
SET heliosdb.current_branch = 'main';
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- If failed, simply delete the branch
SELECT heliosdb.delete_branch('schema-test');

Use Case 2: Production Debugging

-- Someone reports data corruption at 2:30 PM
SELECT heliosdb.create_branch(
branch_name => 'debug-2025-10-24',
parent_branch => 'main',
from_timestamp => '2025-10-24 14:30:00'
);
-- Switch to debug branch
SET heliosdb.current_branch = 'debug-2025-10-24';
-- Investigate without affecting production
SELECT * FROM transactions
WHERE status = 'corrupted'
AND created_at BETWEEN '2025-10-24 14:00:00' AND '2025-10-24 15:00:00';
-- When done, delete debug branch
SELECT heliosdb.delete_branch('debug-2025-10-24');

Use Case 3: Feature Development

-- Developer creates feature branch
SELECT heliosdb.create_branch('feature-payment-v2', 'main');
SET heliosdb.current_branch = 'feature-payment-v2';
-- Develop and test with real data
CREATE TABLE payment_methods (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
method_type VARCHAR(50),
details JSONB
);
-- Test with production-like data
INSERT INTO payment_methods (user_id, method_type, details)
SELECT id, 'credit_card', '{"last4": "1234"}'::jsonb
FROM users LIMIT 1000;
-- Run integration tests
-- If tests pass, merge changes to main
-- If tests fail, delete branch and start over

Use Case 4: A/B Testing Queries

-- Create branch for testing query optimization
SELECT heliosdb.create_branch('query-optimization', 'main');
SET heliosdb.current_branch = 'query-optimization';
-- Test new index strategy
CREATE INDEX CONCURRENTLY idx_orders_complex
ON orders (user_id, status, created_at);
-- Compare performance
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE user_id = 123 AND status = 'pending'
ORDER BY created_at DESC LIMIT 10;
-- Switch back to main and compare
SET heliosdb.current_branch = 'main';
EXPLAIN ANALYZE
SELECT * FROM orders
WHERE user_id = 123 AND status = 'pending'
ORDER BY created_at DESC LIMIT 10;

Troubleshooting

Issue: Cannot Create Branch

Symptom:

ERROR: Failed to create branch: MaxBranchesReached

Solution:

-- Check current branch count
SELECT COUNT(*) FROM heliosdb.branches WHERE state = 'Active';
-- Delete unused branches
SELECT heliosdb.delete_branch(name)
FROM heliosdb.branches
WHERE state = 'Active'
AND age(now(), created_at) > interval '30 days'
AND name LIKE 'debug-%';

Issue: Branch Storage Growing

Symptom: Branch using more storage than expected

Solution:

-- Check branch statistics
SELECT name, storage_mb, divergence_percent
FROM heliosdb.branch_stats()
ORDER BY storage_mb DESC;
-- Manually trigger garbage collection
SELECT heliosdb.gc_branch('feature-auth');
-- Adjust GC retention period
ALTER BRANCH 'feature-auth' SET gc_retention_days = 7;

Issue: Slow Queries on Branch

Symptom: Queries slower on branch than main

Solution:

-- Check branch depth (deep branches have overhead)
SELECT name, depth FROM heliosdb.branches;
-- Create fresh branch from current main
SELECT heliosdb.create_branch('feature-auth-v2', 'main');
-- Migrate work to new branch
-- Delete old deep branch
SELECT heliosdb.delete_branch('feature-auth');

Issue: Cannot Delete Branch with Children

Symptom:

ERROR: Cannot delete branch with children

Solution:

-- List child branches
SELECT b2.name as child_branch
FROM heliosdb.branches b1
JOIN heliosdb.branches b2 ON b2.parent_id = b1.id
WHERE b1.name = 'feature-parent';
-- Delete children first
SELECT heliosdb.delete_branch('feature-child-1');
SELECT heliosdb.delete_branch('feature-child-2');
-- Now delete parent
SELECT heliosdb.delete_branch('feature-parent');

Performance Tuning Tips

1. Minimize Branch Depth

Keep branches shallow (depth <= 3) for best performance:

-- Avoid: branch → sub-branch → sub-sub-branch
-- Prefer: branch → main (depth 1)
-- Recreate from main instead of branching from branches
SELECT heliosdb.create_branch('feature-v2', 'main'); -- Good
-- vs
SELECT heliosdb.create_branch('feature-v2', 'feature-v1'); -- Avoid

2. Regular Garbage Collection

-- Enable automatic GC
ALTER DATABASE heliosdb SET heliosdb.auto_gc = true;
ALTER DATABASE heliosdb SET heliosdb.gc_interval = 3600; -- hourly
-- Manual GC for specific branch
SELECT heliosdb.gc_branch('branch-name');

3. Limit Branch Lifetime

-- Set expiration on temporary branches
SELECT heliosdb.create_branch(
branch_name => 'temp-debug',
parent_branch => 'main',
expires_at => now() + interval '24 hours'
);

4. Monitor Storage Usage

-- Create monitoring view
CREATE VIEW branch_health AS
SELECT
name,
depth,
storage_mb,
divergence_percent,
age(now(), created_at) as age,
CASE
WHEN depth > 3 THEN 'Too Deep'
WHEN storage_mb > 100 THEN 'Too Large'
WHEN age(now(), created_at) > interval '7 days' THEN 'Old'
ELSE 'Healthy'
END as health_status
FROM heliosdb.branch_stats();
-- Query regularly
SELECT * FROM branch_health WHERE health_status != 'Healthy';

5. Optimize Write Patterns

-- Batch writes when possible
BEGIN;
SET heliosdb.current_branch = 'feature-branch';
INSERT INTO users SELECT * FROM staging_users;
INSERT INTO orders SELECT * FROM staging_orders;
COMMIT;
-- vs multiple small transactions (slower)

Best Practices

Branch Naming Convention

-- Use consistent naming
feature/<feature-name> -- Feature development
bugfix/<bug-id> -- Bug fixes
debug/<date> -- Debug sessions
test/<test-name> -- Testing
hotfix/<issue> -- Production hotfixes
-- Examples:
SELECT heliosdb.create_branch('feature/user-auth', 'main');
SELECT heliosdb.create_branch('debug/2025-10-24', 'main',
from_timestamp => '2025-10-24 14:30:00');

Branch Lifecycle

-- 1. Create with clear purpose
SELECT heliosdb.create_branch('feature/new-api', 'main');
-- 2. Set context
SET heliosdb.current_branch = 'feature/new-api';
-- 3. Do work
-- ... development ...
-- 4. Test thoroughly
-- ... testing ...
-- 5. Merge to main (application-level merge)
-- Copy successful changes to main
-- 6. Clean up
SELECT heliosdb.delete_branch('feature/new-api');

Security Considerations

-- Restrict branch creation in production
REVOKE EXECUTE ON FUNCTION heliosdb.create_branch FROM public;
GRANT EXECUTE ON FUNCTION heliosdb.create_branch TO admin_role;
-- Audit branch operations
CREATE TABLE branch_audit (
operation TEXT,
branch_name TEXT,
user_name TEXT,
timestamp TIMESTAMPTZ DEFAULT now()
);
-- Log all branch operations
CREATE OR REPLACE FUNCTION log_branch_operation()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO branch_audit (operation, branch_name, user_name)
VALUES (TG_OP, NEW.name, current_user);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Resource Limits

-- Set per-user branch limits
ALTER ROLE developer_user SET heliosdb.max_branches = 5;
-- Set organization-wide limits
ALTER DATABASE heliosdb SET heliosdb.max_total_branches = 100;
-- Monitor quota usage
SELECT
current_user,
COUNT(*) as branch_count,
current_setting('heliosdb.max_branches')::int as limit
FROM heliosdb.branches
WHERE owner = current_user
GROUP BY current_user;

Integration with CI/CD

GitHub Actions Example

name: Database Tests
on: [pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Create test branch
run: |
psql $DATABASE_URL -c "
SELECT heliosdb.create_branch(
'ci-test-${{ github.run_id }}',
'main'
);
"
- name: Run migrations
run: |
export HELIOSDB_BRANCH="ci-test-${{ github.run_id }}"
./migrate.sh
- name: Run tests
run: |
export HELIOSDB_BRANCH="ci-test-${{ github.run_id }}"
npm test
- name: Cleanup
if: always()
run: |
psql $DATABASE_URL -c "
SELECT heliosdb.delete_branch('ci-test-${{ github.run_id }}');
"

Monitoring and Observability

Key Metrics to Monitor

-- Branch count over time
SELECT COUNT(*) as active_branches
FROM heliosdb.branches
WHERE state = 'Active';
-- Total branch storage
SELECT SUM(storage_mb) as total_branch_storage_mb
FROM heliosdb.branch_stats();
-- Branch age distribution
SELECT
CASE
WHEN age < interval '1 day' THEN '<1 day'
WHEN age < interval '7 days' THEN '1-7 days'
WHEN age < interval '30 days' THEN '7-30 days'
ELSE '>30 days'
END as age_bucket,
COUNT(*) as branch_count
FROM (
SELECT age(now(), created_at) as age
FROM heliosdb.branches
) sub
GROUP BY age_bucket;

Prometheus Metrics

# Add to prometheus.yml
scrape_configs:
- job_name: 'heliosdb_branches'
static_configs:
- targets: ['localhost:9090']
metrics_path: '/metrics/branches'

Exported metrics:

  • heliosdb_branches_total: Total number of branches
  • heliosdb_branch_storage_bytes: Storage per branch
  • heliosdb_branch_depth: Branch depth
  • heliosdb_branch_age_seconds: Age of each branch

Advanced Topics

Cross-Branch Queries

-- Join data across branches
SELECT
m.user_id,
m.balance as main_balance,
f.balance as feature_balance,
f.balance - m.balance as difference
FROM main.accounts m
JOIN feature_payment.accounts f ON m.user_id = f.user_id
WHERE f.balance != m.balance;

Branch Merging Strategies

While HeliosDB doesn’t have automatic merge, you can implement merge logic:

-- Application-level merge
BEGIN;
-- 1. Switch to main
SET heliosdb.current_branch = 'main';
-- 2. Apply changes from feature branch
INSERT INTO users
SELECT * FROM feature_auth.users
WHERE id NOT IN (SELECT id FROM users);
UPDATE users u
SET email = f.email, name = f.name
FROM feature_auth.users f
WHERE u.id = f.id AND (u.email != f.email OR u.name != f.name);
COMMIT;
-- 3. Delete feature branch
SELECT heliosdb.delete_branch('feature-auth');

Conclusion

Git-style branching in HeliosDB provides powerful capabilities for development, testing, and debugging with minimal storage overhead and instant creation times. By following the best practices in this guide, you can safely experiment with your database while maintaining production stability.

For more information, see:

  • API Reference: /docs/api/branching.md
  • Architecture Details: /docs/architecture/BRANCHING_ARCHITECTURE.md
  • Performance Tuning: /docs/performance/branching-optimization.md