PostgreSQL to HeliosDB Lite Migration

HeliosDB Lite takes over workloads from PostgreSQL through the same wire protocol: the schema and data are exported with pg_dump, statements for features Lite handles differently, such as extensions, are removed from the dump, the result is loaded into the Lite server with psql, and the application then connects with its existing PostgreSQL driver.

Problem Being Solved

Core Problem Statement

PostgreSQL's client-server architecture imposes unnecessary network overhead, operational complexity, and cloud infrastructure costs for applications that could run with embedded databases.

Who Suffers Most

  1. ISV Software Vendors (Packaged Applications): Shipping software that requires customers to provision PostgreSQL clusters; customers complain about setup complexity and cloud costs; support burden for database configuration/tuning issues; lost deals due to "too complex to deploy."


HeliosDB Lite Solution

Architecture Overview

┌────────────────────────────────────────────────────────────────┐
│                     Application Process                         │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │           Application Code (Rust/Python/Node/Go)          │  │
│  │                                                            │  │
│  │  PostgreSQL Client Library (libpq, node-postgres, etc.)  │  │
│  └────────────────────────┬───────────────────────────────────┘  │
│                           │                                     │
│                           │ postgresql://localhost/db           │
│                           │ (connection string)                 │
│                           ▼                                     │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │              HeliosDB-Lite Wire Adapter                   │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │  PostgreSQL Wire Protocol Handler                   │  │  │
│  │  │  - Startup message parsing                          │  │  │
│  │  │  - Query protocol (Simple/Extended)                 │  │  │
│  │  │  - Data type encoding (text/binary)                 │  │  │
│  │  │  - COPY protocol                                    │  │  │
│  │  │  - Authentication (trust/password)                  │  │  │
│  │  └────────────────────┬───────────────────────────────┘  │  │
│  │                       ▼                                   │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │  SQL Dialect Translator                             │  │  │
│  │  │  - PostgreSQL → SQLite SQL conversion               │  │  │
│  │  │  - Function mapping (NOW() → datetime('now'))       │  │  │
│  │  │  - Type mapping (SERIAL → INTEGER PRIMARY KEY)      │  │  │
│  │  │  - RETURNING clause emulation                       │  │  │
│  │  └────────────────────┬───────────────────────────────┘  │  │
│  │                       ▼                                   │  │
│  └───────────────────────────────────────────────────────────┘  │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │              HeliosDB-Lite Core Engine                    │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │  SQL Query Engine                                   │  │  │
│  │  │  - Query parser & optimizer                         │  │  │
│  │  │  - Execution engine                                 │  │  │
│  │  │  - Index management                                 │  │  │
│  │  └────────────────────┬───────────────────────────────┘  │  │
│  │                       ▼                                   │  │
│  │  ┌────────────────────────────────────────────────────┐  │  │
│  │  │  Storage Layer (SQLite-compatible)                  │  │  │
│  │  │  - B-tree indexes                                   │  │  │
│  │  │  - WAL (Write-Ahead Logging)                        │  │  │
│  │  │  - ACID transactions                                │  │  │
│  │  │  - Page cache (configurable)                        │  │  │
│  │  └────────────────────┬───────────────────────────────┘  │  │
│  │                       ▼                                   │  │
│  │                   app_data.db                             │  │
│  │              (Single file on disk)                        │  │
│  └──────────────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────────────┘
                        Single Process
                    Zero Network Overhead
            No Separate Database Server Required

Concrete Examples with Code, Config & Architecture

Example 1: Embedded Configuration for PostgreSQL Migration

HeliosDB Lite Configuration (helios_postgres_compat.toml):

[database]
type = "embedded"
path = "./app_data.db"
mode = "readwrite-create"
page_size = 8192  # Match PostgreSQL page size
cache_size_mb = 512
wal_mode = true
sync_mode = "full"  # ACID compliance
journal_mode = "wal"

[postgres_compatibility]
enabled = true
listen_address = "127.0.0.1"
listen_port = 5432
max_connections = 100
authentication_mode = "trust"  # or "md5", "scram-sha-256"

# SQL dialect translation
[dialect]
target_dialect = "postgresql"
translate_functions = true
translate_types = true
emulate_sequences = true
support_returning = true
support_cte = true
support_window_functions = true

# Type mappings
[dialect.type_mappings]
"SERIAL" = "INTEGER PRIMARY KEY AUTOINCREMENT"
"BIGSERIAL" = "INTEGER PRIMARY KEY AUTOINCREMENT"
"TEXT" = "TEXT"
"VARCHAR" = "TEXT"
"TIMESTAMP" = "TEXT"  # ISO8601 format
"TIMESTAMPTZ" = "TEXT"
"JSONB" = "TEXT"  # JSON functions supported
"UUID" = "TEXT"
"INET" = "TEXT"
"BOOLEAN" = "INTEGER"  # 0/1

# Function mappings
[dialect.function_mappings]
"NOW()" = "datetime('now')"
"CURRENT_TIMESTAMP" = "datetime('now')"
"CURRENT_DATE" = "date('now')"
"RANDOM()" = "random()"
"COALESCE" = "COALESCE"  # Passthrough
"NULLIF" = "NULLIF"
"GREATEST" = "MAX"
"LEAST" = "MIN"

# pg_dump import settings
[import]
buffer_size_mb = 128
use_transactions = true
skip_on_error = false
log_file = "./import.log"

[performance]
optimize_queries = true
auto_vacuum = true
vacuum_interval_hours = 24
analyze_on_import = true

[monitoring]
log_queries = false
log_slow_queries_ms = 1000
export_metrics = true
metrics_port = 9091

Migration Script (migrate_from_postgres.sh):

#!/bin/bash

set -e

echo " PostgreSQL to HeliosDB-Lite Migration"
echo "========================================="

# Configuration
POSTGRES_HOST="myapp-db.xxx.rds.amazonaws.com"
POSTGRES_PORT="5432"
POSTGRES_DB="production"
POSTGRES_USER="admin"
DUMP_FILE="./postgres_dump.sql"
HELIOS_CONFIG="./helios_postgres_compat.toml"
HELIOS_DB="./app_data.db"

echo ""
echo "Step 1: Export PostgreSQL database using pg_dump"
echo "------------------------------------------------"
pg_dump -h "$POSTGRES_HOST" \
        -p "$POSTGRES_PORT" \
        -U "$POSTGRES_USER" \
        -d "$POSTGRES_DB" \
        --format=plain \
        --no-owner \
        --no-privileges \
        --clean \
        --if-exists \
        > "$DUMP_FILE"

echo " Dump created: $(wc -l < $DUMP_FILE) lines, $(du -h $DUMP_FILE | cut -f1)"

echo ""
echo "Step 2: Import into HeliosDB-Lite"
echo "----------------------------------"
heliosdb-lite import \
    --config "$HELIOS_CONFIG" \
    --input "$DUMP_FILE" \
    --database "$HELIOS_DB" \
    --format pg_dump \
    --verbose

echo " Import complete"

echo ""
echo "Step 3: Verify migration"
echo "------------------------"
heliosdb-lite query \
    --database "$HELIOS_DB" \
    --sql "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"

echo ""
echo "Step 4: Analyze & optimize"
echo "--------------------------"
heliosdb-lite exec \
    --database "$HELIOS_DB" \
    --command "VACUUM; ANALYZE;"

echo " Database optimized"

echo ""
echo "Step 5: Test query compatibility"
echo "--------------------------------"
# Run sample queries to test translation
heliosdb-lite query \
    --database "$HELIOS_DB" \
    --sql "SELECT COUNT(*) as total_users FROM users;"

heliosdb-lite query \
    --database "$HELIOS_DB" \
    --sql "SELECT NOW() as current_time;"

echo ""
echo " Migration complete!"
echo ""
echo "Next steps:"
echo "1. Update application connection string to: postgresql://localhost:5432/$POSTGRES_DB"
echo "2. Start HeliosDB-Lite wire adapter: heliosdb-lite serve --config $HELIOS_CONFIG"
echo "3. Test application thoroughly"

Example 2: Python Application Migration (Django/SQLAlchemy)

Django Migration (settings.py):

# BEFORE: PostgreSQL on RDS
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'production',
        'USER': 'admin',
        'PASSWORD': 'secret',
        'HOST': 'myapp-db.xxx.rds.amazonaws.com',
        'PORT': '5432',
        'CONN_MAX_AGE': 600,
        'OPTIONS': {
            'connect_timeout': 10,
            'sslmode': 'require',
        }
    }
}

# AFTER: HeliosDB-Lite with PostgreSQL wire protocol
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'production',
        'USER': 'app',
        'PASSWORD': '',  # Trust authentication
        'HOST': '127.0.0.1',
        'PORT': '5432',
        'CONN_MAX_AGE': 0,  # Embedded DB doesn't need pooling
        'OPTIONS': {
            'connect_timeout': 1,
        }
    }
}

# That's it! Zero model changes needed.

Architecture Diagram:

┌──────────────────────────────────────────────────────────┐
│                 Python Application                        │
│  ┌────────────────────────────────────────────────────┐  │
│  │  Django / Flask / FastAPI                          │  │
│  │  - Models (ORM)                                    │  │
│  │  - Views/Routes                                    │  │
│  │  - Business Logic                                  │  │
│  └─────────────────┬──────────────────────────────────┘  │
│                    │                                     │
│                    │ psycopg2 / asyncpg                  │
│                    │ (PostgreSQL driver)                 │
│                    ▼                                     │
│  ┌────────────────────────────────────────────────────┐  │
│  │  HeliosDB-Lite PostgreSQL Wire Adapter             │  │
│  │  - Protocol handler (localhost:5432)               │  │
│  │  - SQL dialect translator                          │  │
│  │  - Type conversions                                │  │
│  └─────────────────┬──────────────────────────────────┘  │
│                    │                                     │
│                    ▼                                     │
│  ┌────────────────────────────────────────────────────┐  │
│  │  HeliosDB-Lite Core (Embedded SQLite)              │  │
│  │  - File: production.db                             │  │
│  │  - ACID transactions                               │  │
│  │  - Full-text search                                │  │
│  └────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────┘

Example 3: Docker & Kubernetes Deployment

Dockerfile (Before - Multi-Container):

# BEFORE: Separate PostgreSQL container
version: '3.8'
services:
  app:
    build: .
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/production
    ports:
      - "8080:8080"

  db:
    image: postgres:15
    environment:
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=production
    volumes:
      - pgdata:/var/lib/postgresql/data
    ports:
      - "5432:5432"

volumes:
  pgdata:

Dockerfile (After - Single Container with HeliosDB Lite):

FROM rust:1.75-slim as builder

WORKDIR /app
COPY Cargo.toml Cargo.lock ./
COPY src ./src

RUN cargo build --release

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy application binary
COPY --from=builder /app/target/release/myapp /usr/local/bin/

# Copy HeliosDB-Lite configuration
COPY helios_postgres_compat.toml /app/config/

# Create data directory
RUN mkdir -p /app/data

# Single process runs both app + embedded DB
ENV DATABASE_URL=postgresql://localhost:5432/production
ENV HELIOS_CONFIG=/app/config/helios_postgres_compat.toml
ENV HELIOS_DB_PATH=/app/data/production.db

EXPOSE 8080

CMD ["myapp"]

docker-compose.yml (Simplified):

version: '3.8'

services:
  app:
    build: .
    container_name: myapp
    ports:
      - "8080:8080"
      - "9091:9091"  # Metrics
    volumes:
      - app-data:/app/data
      - ./config:/app/config:ro
    environment:
      - RUST_LOG=info
      - HELIOS_DB_PATH=/app/data/production.db
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    restart: unless-stopped
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '0.5'
          memory: 512M

volumes:
  app-data:
    driver: local

Kubernetes Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myregistry/myapp:latest
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 9091
          name: metrics
        env:
        - name: HELIOS_DB_PATH
          value: "/data/production.db"
        - name: DATABASE_URL
          value: "postgresql://localhost:5432/production"
        volumeMounts:
        - name: data
          mountPath: /data
        - name: config
          mountPath: /app/config
          readOnly: true
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "2Gi"
            cpu: "2000m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: myapp-data-pvc
      - name: config
        configMap:
          name: helios-config
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: production
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: myapp
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myapp-data-pvc
  namespace: production
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 100Gi

Example 4: Node.js Migration with Connection Pooling

Node.js Application (Before):

const { Pool } = require('pg');

// BEFORE: RDS PostgreSQL with connection pooling
const pool = new Pool({
  host: 'myapp-db.xxx.rds.amazonaws.com',
  port: 5432,
  database: 'production',
  user: 'admin',
  password: process.env.DB_PASSWORD,
  max: 20,  // Connection pool size
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 2000,
  ssl: { rejectUnauthorized: false }
});

async function getUsers() {
  const client = await pool.connect();
  try {
    const result = await client.query('SELECT * FROM users LIMIT 10');
    return result.rows;
  } finally {
    client.release();
  }
}

async function createUser(name, email) {
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    const result = await client.query(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id',
      [name, email]
    );
    await client.query('COMMIT');
    return result.rows[0].id;
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

module.exports = { getUsers, createUser };

Node.js Application (After - HeliosDB Lite):

const { Pool } = require('pg');

// AFTER: HeliosDB-Lite via localhost
const pool = new Pool({
  host: '127.0.0.1',
  port: 5432,
  database: 'production',
  user: 'app',
  max: 1,  // Embedded DB doesn't need pooling
  idleTimeoutMillis: 30000,
  connectionTimeoutMillis: 500,  // Local connection is fast
  // No SSL needed for localhost
});

// ZERO CHANGES TO APPLICATION CODE BELOW
async function getUsers() {
  const client = await pool.connect();
  try {
    const result = await client.query('SELECT * FROM users LIMIT 10');
    return result.rows;
  } finally {
    client.release();
  }
}

async function createUser(name, email) {
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    const result = await client.query(
      'INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id',
      [name, email]
    );
    await client.query('COMMIT');
    return result.rows[0].id;
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
}

// Performance test
async function benchmarkQueries() {
  console.log('Running benchmark...\n');

  // Test 1: Simple SELECT
  const start1 = Date.now();
  for (let i = 0; i < 1000; i++) {
    await pool.query('SELECT 1');
  }
  const latency1 = Date.now() - start1;
  console.log(` 1000 SELECT queries: ${latency1}ms (${latency1/1000}ms avg)`);

  // Test 2: INSERT with RETURNING
  const start2 = Date.now();
  for (let i = 0; i < 100; i++) {
    await pool.query(
      'INSERT INTO test_table (value) VALUES ($1) RETURNING id',
      [i]
    );
  }
  const latency2 = Date.now() - start2;
  console.log(` 100 INSERT queries: ${latency2}ms (${latency2/100}ms avg)`);

  // Test 3: Transaction
  const start3 = Date.now();
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    for (let i = 0; i < 50; i++) {
      await client.query('INSERT INTO test_table (value) VALUES ($1)', [i]);
    }
    await client.query('COMMIT');
  } finally {
    client.release();
  }
  const latency3 = Date.now() - start3;
  console.log(` 50-statement transaction: ${latency3}ms`);
}

module.exports = { getUsers, createUser, benchmarkQueries };

Example 5: Go Microservice Migration

Go Application with PostgreSQL:

package main

import (
    "context"
    "database/sql"
    "fmt"
    "log"
    "time"

    _ "github.com/lib/pq"
)

type User struct {
    ID        int
    Name      string
    Email     string
    CreatedAt time.Time
}

func main() {
    // BEFORE: RDS PostgreSQL
    // connStr := "postgresql://admin:secret@myapp-db.xxx.rds.amazonaws.com:5432/production?sslmode=require"

    // AFTER: HeliosDB-Lite
    connStr := "postgresql://app@localhost:5432/production?sslmode=disable"

    db, err := sql.Open("postgres", connStr)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()

    // Configure connection pool (not needed for embedded, but harmless)
    db.SetMaxOpenConns(5)
    db.SetMaxIdleConns(2)
    db.SetConnMaxLifetime(time.Hour)

    // Test connection
    ctx := context.Background()
    if err := db.PingContext(ctx); err != nil {
        log.Fatal("Cannot connect:", err)
    }

    fmt.Println(" Connected to database")

    // Test PostgreSQL features
    testPostgreSQLFeatures(ctx, db)
}

func testPostgreSQLFeatures(ctx context.Context, db *sql.DB) {
    fmt.Println("\nTesting PostgreSQL compatibility...\n")

    // 1. CREATE TABLE with SERIAL
    _, err := db.ExecContext(ctx, `
        CREATE TABLE IF NOT EXISTS users (
            id SERIAL PRIMARY KEY,
            name VARCHAR(100) NOT NULL,
            email VARCHAR(255) UNIQUE NOT NULL,
            created_at TIMESTAMP DEFAULT NOW()
        )
    `)
    if err != nil {
        log.Fatal("CREATE TABLE failed:", err)
    }
    fmt.Println(" CREATE TABLE with SERIAL type")

    // 2. INSERT with RETURNING
    var userID int
    err = db.QueryRowContext(ctx,
        "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id",
        "David", "david@example.com",
    ).Scan(&userID)
    if err != nil {
        log.Fatal("INSERT RETURNING failed:", err)
    }
    fmt.Printf(" INSERT RETURNING: User ID = %d\n", userID)

    // 3. NOW() function
    var currentTime time.Time
    err = db.QueryRowContext(ctx, "SELECT NOW()").Scan(&currentTime)
    if err != nil {
        log.Fatal("NOW() failed:", err)
    }
    fmt.Printf(" NOW() function: %s\n", currentTime.Format(time.RFC3339))

    // 4. CTE (Common Table Expression)
    rows, err := db.QueryContext(ctx, `
        WITH recent_users AS (
            SELECT id, name, email FROM users
            ORDER BY id DESC LIMIT 5
        )
        SELECT * FROM recent_users
    `)
    if err != nil {
        log.Fatal("CTE query failed:", err)
    }
    defer rows.Close()

    count := 0
    for rows.Next() {
        var user User
        if err := rows.Scan(&user.ID, &user.Name, &user.Email); err != nil {
            log.Fatal(err)
        }
        count++
    }
    fmt.Printf(" CTE query: %d users\n", count)

    // 5. Transaction with savepoints
    tx, err := db.BeginTx(ctx, nil)
    if err != nil {
        log.Fatal("BEGIN failed:", err)
    }

    _, err = tx.ExecContext(ctx,
        "INSERT INTO users (name, email) VALUES ($1, $2)",
        "Emma", "emma@example.com",
    )
    if err != nil {
        tx.Rollback()
        log.Fatal("Transaction failed:", err)
    }

    if err = tx.Commit(); err != nil {
        log.Fatal("COMMIT failed:", err)
    }
    fmt.Println(" Transaction committed")

    // 6. Prepared statement
    stmt, err := db.PrepareContext(ctx,
        "SELECT id, name, email FROM users WHERE email = $1",
    )
    if err != nil {
        log.Fatal("Prepare failed:", err)
    }
    defer stmt.Close()

    var user User
    err = stmt.QueryRowContext(ctx, "david@example.com").Scan(
        &user.ID, &user.Name, &user.Email,
    )
    if err != nil {
        log.Fatal("Prepared query failed:", err)
    }
    fmt.Printf(" Prepared statement: Found user %s\n", user.Name)

    fmt.Println("\nAll checks passed.")
}

func benchmarkQueries(ctx context.Context, db *sql.DB) {
    fmt.Println("\nRunning benchmark...\n")

    // Benchmark: 1000 simple queries
    start := time.Now()
    for i := 0; i < 1000; i++ {
        var result int
        db.QueryRowContext(ctx, "SELECT 1").Scan(&result)
    }
    elapsed := time.Since(start)
    fmt.Printf(" 1000 queries: %v (%.2fms avg)\n",
        elapsed, float64(elapsed.Milliseconds())/1000.0)

    // Benchmark: Bulk insert
    start = time.Now()
    tx, _ := db.BeginTx(ctx, nil)
    for i := 0; i < 1000; i++ {
        tx.ExecContext(ctx,
            "INSERT INTO test_data (value) VALUES ($1)", i,
        )
    }
    tx.Commit()
    elapsed = time.Since(start)
    fmt.Printf(" 1000 inserts in transaction: %v\n", elapsed)
}

Architecture Diagram:

┌────────────────────────────────────────────────────────┐
│                Go Microservice                          │
│  ┌──────────────────────────────────────────────────┐  │
│  │  HTTP Server (Gin/Echo/Chi)                      │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │  Business Logic                             │  │  │
│  │  │  - User service                             │  │  │
│  │  │  - Order service                            │  │  │
│  │  │  - Payment service                          │  │  │
│  │  └────────────────┬───────────────────────────┘  │  │
│  │                   │                               │  │
│  │                   │ lib/pq (PostgreSQL driver)    │  │
│  │                   ▼                               │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │  database/sql                               │  │  │
│  │  │  - Connection pooling                       │  │  │
│  │  │  - Prepared statements                      │  │  │
│  │  └────────────────┬───────────────────────────┘  │  │
│  └───────────────────┼───────────────────────────────┘  │
│                      │ TCP localhost:5432               │
│                      ▼                                  │
│  ┌──────────────────────────────────────────────────┐  │
│  │  HeliosDB-Lite Wire Adapter                      │  │
│  │  - PostgreSQL protocol                           │  │
│  │  - SQL translation                               │  │
│  └──────────────────┬───────────────────────────────┘  │
│                     │                                  │
│                     ▼                                  │
│  ┌──────────────────────────────────────────────────┐  │
│  │  HeliosDB-Lite Embedded (production.db)          │  │
│  └──────────────────────────────────────────────────┘  │
└────────────────────────────────────────────────────────┘

Adoption Strategy

Phase 1: Assessment & Planning (Week 1)

  1. Inventory PostgreSQL Usage: List all databases, sizes, query patterns
  2. Estimate Savings: Calculate current RDS costs vs. embedded approach
  3. Select Pilot Service: Choose non-critical microservice with low risk

Phase 2: Pilot Migration (Weeks 2-3)

  1. Export Database: pg_dump -Fc production > dump.sql
  2. Import to HeliosDB Lite: heliosdb-lite import --format pg_dump dump.sql
  3. Update Connection String: Change postgresql://rds-host:5432/db to postgresql://localhost:5432/db
  4. Deploy & Test: Run integration tests; compare query results
  5. Load Test: Verify performance under production traffic patterns
  6. Monitor: Track latency, errors, resource usage for 1 week

Phase 3: Rollout (Weeks 4-12)

  1. Tune Performance: Optimize page cache, vacuum settings
  2. Update Documentation: Deployment guides, runbooks
  3. Train Team: Best practices for embedded databases

Conclusion

HeliosDB Lite bridges this gap by providing wire protocol compatibility with PostgreSQL while delivering the operational simplicity and performance of embedded databases.

Performance depends on workload and hardware. Published figures are measured on representative fixtures; see the benchmarks page and reproduce them on your own workload.