PostgreSQL Wire Protocol Compatibility

HeliosDB Lite lets applications built for PostgreSQL connect with their existing drivers, ORMs and tools such as psql: the server speaks the PostgreSQL wire protocol with the simple and extended query protocols, prepared statements, transactions, password, MD5 and SCRAM-SHA-256 authentication, TLS, COPY for bulk loads and LISTEN/NOTIFY, and its catalogs cover the common client and ORM introspection paths.

Problem Being Solved

Core Problem Statement

Development teams invest heavily in PostgreSQL expertise, tooling, and application code, but face prohibitive complexity when attempting to run similar workloads in embedded, edge, or microservice environments where full PostgreSQL server deployment is impractical.


HeliosDB Lite Solution

Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│              PostgreSQL Client Ecosystem (Unchanged)                 │
├─────────────────────────────────────────────────────────────────────┤
│  psql │ pgAdmin │ DBeaver │ psycopg2 │ node-postgres │ JDBC │ sqlx  │
├─────────────────────────────────────────────────────────────────────┤
│            PostgreSQL v3.0 Wire Protocol (TCP/SSL)                   │
├─────────────────────────────────────────────────────────────────────┤
│  HeliosDB-Lite Protocol Handler (Async Tokio)                        │
│  ├── Authentication (SCRAM-SHA-256, MD5)                             │
│  ├── Simple Query Protocol                                           │
│  ├── Extended Query Protocol (Parse → Bind → Execute)                │
│  └── Prepared Statement Manager (LRU Cache, 100 statements)          │
├─────────────────────────────────────────────────────────────────────┤
│  SQL Query Engine & Execution                                        │
├─────────────────────────────────────────────────────────────────────┤
│  Embedded RocksDB LSM Storage (No External Database)                 │
└─────────────────────────────────────────────────────────────────────┘

Concrete Examples with Code, Config & Architecture

Example 2: Node.js with node-postgres - ORM Compatibility (Prisma)

Architecture:

┌─────────────────────────────────────┐
│   Retail Store (Offline-Capable)    │
├─────────────────────────────────────┤
│  Next.js Frontend                   │
├─────────────────────────────────────┤
│  Prisma ORM (Unchanged)             │
├─────────────────────────────────────┤
│  node-postgres Driver               │
├─────────────────────────────────────┤
│  HeliosDB-Lite Embedded Server      │
│  (Runs in Electron/Desktop App)     │
├─────────────────────────────────────┤
│  Local SQLite-style Storage         │
│  (Syncs to Cloud When Online)       │
└─────────────────────────────────────┘

Prisma Schema (schema.prisma - UNCHANGED):

// Prisma schema works identically with HeliosDB-Lite
datasource db {
  provider = "postgresql"  // No change needed!
  url      = env("DATABASE_URL")
}

generator client {
  provider = "prisma-client-js"
}

model Product {
  id          Int      @id @default(autoincrement())
  sku         String   @unique
  name        String
  description String?
  price       Decimal  @db.Decimal(10, 2)
  stock       Int      @default(0)
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  sales       Sale[]

  @@index([sku])
}

model Sale {
  id         Int      @id @default(autoincrement())
  productId  Int
  quantity   Int
  totalPrice Decimal  @db.Decimal(10, 2)
  soldAt     DateTime @default(now())
  synced     Boolean  @default(false)

  product    Product  @relation(fields: [productId], references: [id])

  @@index([synced, soldAt])
}

Environment Configuration (.env):

# Local embedded database (change from cloud)
DATABASE_URL="postgresql://pos_user:password@localhost:5432/retail_store_001?sslmode=disable"

# Production (cloud sync endpoint)
CLOUD_SYNC_URL="https://api.mystore.com/sync"

Application Code (TypeScript):

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient({
  datasources: {
    db: {
      url: process.env.DATABASE_URL,
    },
  },
});

// CRUD operations identical to PostgreSQL
async function createProduct(data: {
  sku: string;
  name: string;
  price: number;
  stock: number;
}) {
  return await prisma.product.create({
    data: {
      sku: data.sku,
      name: data.name,
      price: data.price,
      stock: data.stock,
    },
  });
}

async function recordSale(productId: number, quantity: number) {
  // Transaction support (uses extended query protocol)
  return await prisma.$transaction(async (tx) => {
    // Check stock
    const product = await tx.product.findUnique({
      where: { id: productId },
    });

    if (!product || product.stock < quantity) {
      throw new Error('Insufficient stock');
    }

    // Update stock
    await tx.product.update({
      where: { id: productId },
      data: { stock: product.stock - quantity },
    });

    // Record sale
    return await tx.sale.create({
      data: {
        productId,
        quantity,
        totalPrice: product.price * quantity,
        synced: false,  // Mark for cloud sync
      },
    });
  });
}

async function getSalesToSync() {
  return await prisma.sale.findMany({
    where: { synced: false },
    include: { product: true },
    orderBy: { soldAt: 'asc' },
    take: 100,
  });
}

async function markSalesSynced(saleIds: number[]) {
  return await prisma.sale.updateMany({
    where: { id: { in: saleIds } },
    data: { synced: true },
  });
}

// $ npx prisma migrate dev --name init
// $ npx prisma migrate deploy

Offline Sync Logic:

import { PrismaClient } from '@prisma/client';
import axios from 'axios';

const prisma = new PrismaClient();

async function syncToCloud() {
  try {
    // Get unsynced sales from HeliosDB-Lite
    const sales = await getSalesToSync();

    if (sales.length === 0) {
      console.log('No sales to sync');
      return;
    }

    // Upload to cloud
    const response = await axios.post(
      process.env.CLOUD_SYNC_URL!,
      { sales },
      { timeout: 30000 }
    );

    if (response.status === 200) {
      // Mark as synced
      const saleIds = sales.map((s) => s.id);
      await markSalesSynced(saleIds);
      console.log(`Synced ${sales.length} sales to cloud`);
    }
  } catch (error) {
    // Stay offline—retry later
    console.warn('Sync failed (offline?), will retry:', error.message);
  }
}

// Sync every 5 minutes when online
setInterval(syncToCloud, 5 * 60 * 1000);

Example 3: Java JDBC Integration - Enterprise Spring Boot Application

Scenario: Enterprise logistics company with 200 Java microservices using Spring Boot + PostgreSQL. PostgreSQL server too heavy; SQLite breaks existing JDBC code.

Spring Boot Configuration (application.yml - MINIMAL CHANGES):

spring:
  datasource:
    # Changed from cloud PostgreSQL to embedded HeliosDB-Lite
    url: jdbc:postgresql://localhost:5432/warehouse_inventory
    username: warehouse_app
    password: ${DB_PASSWORD}
    driver-class-name: org.postgresql.Driver

    # Connection pool (HikariCP)
    hikari:
      maximum-pool-size: 10
      minimum-idle: 2
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

  jpa:
    database-platform: org.hibernate.dialect.PostgreSQLDialect
    hibernate:
      ddl-auto: validate
    properties:
      hibernate:
        jdbc:
          batch_size: 50
        order_inserts: true
        order_updates: true

# HeliosDB-specific tuning (optional)
heliosdb:
  memory_limit_mb: 128
  wal_enabled: true
  prepared_statement_cache: 100

JPA Entity (UNCHANGED from PostgreSQL):

package com.logistics.inventory.entity;

import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;

@Entity
@Table(name = "inventory_items", indexes = {
    @Index(name = "idx_sku", columnList = "sku"),
    @Index(name = "idx_warehouse_sku", columnList = "warehouse_id, sku")
})
public class InventoryItem {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 50)
    private String sku;

    @Column(nullable = false)
    private String warehouseId;

    @Column(nullable = false)
    private Integer quantity;

    @Column(precision = 10, scale = 2)
    private BigDecimal unitPrice;

    @Column(nullable = false)
    private LocalDateTime lastUpdated;

    @Column(nullable = false)
    private Boolean synced = false;

    // Getters and setters (unchanged)
    // ...
}

Repository (Spring Data JPA - UNCHANGED):

package com.logistics.inventory.repository;

import com.logistics.inventory.entity.InventoryItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface InventoryItemRepository extends JpaRepository<InventoryItem, Long> {

    // Query methods work identically with HeliosDB-Lite
    Optional<InventoryItem> findBySkuAndWarehouseId(String sku, String warehouseId);

    List<InventoryItem> findByWarehouseIdAndSyncedFalse(String warehouseId);

    @Query("SELECT i FROM InventoryItem i WHERE i.quantity < :threshold AND i.warehouseId = :warehouseId")
    List<InventoryItem> findLowStockItems(String warehouseId, Integer threshold);

    // Native query (PostgreSQL syntax works)
    @Query(value = "SELECT * FROM inventory_items WHERE synced = false ORDER BY last_updated LIMIT :limit", nativeQuery = true)
    List<InventoryItem> findUnsyncedItemsForBatch(int limit);
}

Service Layer (Business Logic - UNCHANGED):

package com.logistics.inventory.service;

import com.logistics.inventory.entity.InventoryItem;
import com.logistics.inventory.repository.InventoryItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class InventoryService {

    @Autowired
    private InventoryItemRepository repository;

    @Transactional
    public InventoryItem updateQuantity(String sku, String warehouseId, int delta) {
        InventoryItem item = repository.findBySkuAndWarehouseId(sku, warehouseId)
            .orElseThrow(() -> new IllegalArgumentException("Item not found"));

        item.setQuantity(item.getQuantity() + delta);
        item.setLastUpdated(LocalDateTime.now());
        item.setSynced(false);  // Mark for sync

        return repository.save(item);
    }

    @Transactional
    public void processScan(String sku, String warehouseId, int scannedQuantity) {
        // Prepared statement reused via JDBC (cached by HeliosDB-Lite)
        InventoryItem item = repository.findBySkuAndWarehouseId(sku, warehouseId)
            .orElseGet(() -> {
                InventoryItem newItem = new InventoryItem();
                newItem.setSku(sku);
                newItem.setWarehouseId(warehouseId);
                newItem.setQuantity(0);
                newItem.setLastUpdated(LocalDateTime.now());
                return newItem;
            });

        item.setQuantity(scannedQuantity);
        item.setLastUpdated(LocalDateTime.now());
        item.setSynced(false);

        repository.save(item);
    }

    public List<InventoryItem> getUnsyncedItems(String warehouseId) {
        return repository.findByWarehouseIdAndSyncedFalse(warehouseId);
    }

    @Transactional
    public void markSynced(List<Long> itemIds) {
        List<InventoryItem> items = repository.findAllById(itemIds);
        items.forEach(item -> item.setSynced(true));
        repository.saveAll(items);
    }
}

JDBC Batch Operations (for high throughput):

package com.logistics.inventory.batch;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class BatchInventoryUpdater {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public void batchUpdateFromScanner(List<InventoryUpdate> updates) {
        // Uses prepared statement (cached by HeliosDB-Lite)
        String sql = """
            INSERT INTO inventory_items (sku, warehouse_id, quantity, last_updated, synced)
            VALUES (?, ?, ?, NOW(), false)
            ON CONFLICT (sku, warehouse_id)
            DO UPDATE SET
                quantity = EXCLUDED.quantity,
                last_updated = EXCLUDED.last_updated,
                synced = false
        """;

        jdbcTemplate.batchUpdate(sql, updates, updates.size(),
            (ps, update) -> {
                ps.setString(1, update.getSku());
                ps.setString(2, update.getWarehouseId());
                ps.setInt(3, update.getQuantity());
            });
    }
}

Example 4: Rust sqlx Integration - High-Performance Microservice

Architecture:

┌───────────────────────────────────┐
│  Analytics Microservice           │
├───────────────────────────────────┤
│  Actix-web HTTP Server            │
├───────────────────────────────────┤
│  sqlx (Compile-time Checked SQL)  │
├───────────────────────────────────┤
│  HeliosDB-Lite (In-Process)       │
│  PostgreSQL Protocol Adapter      │
├───────────────────────────────────┤
│  RocksDB LSM Storage (2GB)        │
└───────────────────────────────────┘

Example 5: Cross-Platform Desktop App - Electron + PostgreSQL Ecosystem

Scenario: Healthcare records desktop app (Windows/macOS/Linux) needs HIPAA-compliant local storage with existing PostgreSQL tooling (pgAdmin for admin tasks, DataGrip for developers). SQLite breaks ecosystem; full PostgreSQL too heavy for desktops.

Architecture:

┌─────────────────────────────────────────┐
│  Electron Desktop App (Windows/Mac)     │
├─────────────────────────────────────────┤
│  React Frontend                          │
├─────────────────────────────────────────┤
│  IPC Bridge (Electron Main Process)     │
├─────────────────────────────────────────┤
│  HeliosDB-Lite Embedded Server           │
│  ├── PostgreSQL Protocol (localhost)    │
│  └── AES-256 Encryption (HIPAA)         │
├─────────────────────────────────────────┤
│  Local Encrypted Database File          │
│  (~/.healthapp/patients.db.encrypted)   │
└─────────────────────────────────────────┘

External Tools (Same Machine):
- pgAdmin 4 → localhost:5432
- DataGrip → localhost:5432
- psql → localhost:5432

Electron Main Process (TypeScript):

import { app, BrowserWindow, ipcMain } from 'electron';
import { spawn, ChildProcess } from 'child_process';
import path from 'path';
import { Client } from 'pg';

let heliosdbProcess: ChildProcess | null = null;
let dbClient: Client | null = null;

async function startHeliosDB() {
  const dbPath = path.join(app.getPath('userData'), 'healthrecords.db');
  const configPath = path.join(app.getPath('userData'), 'heliosdb.toml');

  // Start HeliosDB-Lite embedded server
  heliosdbProcess = spawn('./bin/heliosdb-lite', [
    '--config', configPath,
    '--data-dir', dbPath,
    '--port', '5432',
    '--host', '127.0.0.1',
  ]);

  heliosdbProcess.stdout?.on('data', (data) => {
    console.log(`HeliosDB: ${data}`);
  });

  // Wait for server ready
  await new Promise((resolve) => setTimeout(resolve, 2000));

  // Connect via standard PostgreSQL client
  dbClient = new Client({
    host: 'localhost',
    port: 5432,
    database: 'healthrecords',
    user: 'healthapp',
    password: process.env.DB_PASSWORD, // Encrypted in OS keychain
  });

  await dbClient.connect();
  console.log('Connected to HeliosDB-Lite via PostgreSQL protocol');
}

// IPC handlers use standard pg client
ipcMain.handle('db:query', async (event, sql: string, params: any[]) => {
  if (!dbClient) throw new Error('Database not initialized');
  const result = await dbClient.query(sql, params);
  return result.rows;
});

ipcMain.handle('db:transaction', async (event, queries: Array<{ sql: string; params: any[] }>) => {
  if (!dbClient) throw new Error('Database not initialized');

  await dbClient.query('BEGIN');
  try {
    const results = [];
    for (const { sql, params } of queries) {
      const result = await dbClient.query(sql, params);
      results.push(result.rows);
    }
    await dbClient.query('COMMIT');
    return results;
  } catch (error) {
    await dbClient.query('ROLLBACK');
    throw error;
  }
});

app.on('ready', async () => {
  await startHeliosDB();
  createWindow();
});

app.on('will-quit', () => {
  dbClient?.end();
  heliosdbProcess?.kill('SIGTERM');
});

React Frontend (TypeScript):

import { useState, useEffect } from 'react';

const { ipcRenderer } = window.require('electron');

interface Patient {
  id: number;
  mrn: string;
  name: string;
  dob: string;
  ssn_encrypted: string;
}

export function PatientSearch() {
  const [patients, setPatients] = useState<Patient[]>([]);
  const [searchTerm, setSearchTerm] = useState('');

  const searchPatients = async () => {
    const results = await ipcRenderer.invoke('db:query',
      'SELECT id, mrn, name, dob, ssn_encrypted FROM patients WHERE name ILIKE $1 LIMIT 50',
      [`%${searchTerm}%`]
    );
    setPatients(results);
  };

  return (
    <div>
      <input
        type="text"
        value={searchTerm}
        onChange={(e) => setSearchTerm(e.target.value)}
        placeholder="Search patients..."
      />
      <button onClick={searchPatients}>Search</button>

      <table>
        <thead>
          <tr>
            <th>MRN</th>
            <th>Name</th>
            <th>Date of Birth</th>
          </tr>
        </thead>
        <tbody>
          {patients.map((p) => (
            <tr key={p.id}>
              <td>{p.mrn}</td>
              <td>{p.name}</td>
              <td>{p.dob}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

Admin Access via pgAdmin (No Code—Standard Tool):

# Administrator connects with pgAdmin to localhost:5432
# Uses HeliosDB-Lite exactly like PostgreSQL:
# - View tables, run queries, export data
# - Create indexes, run VACUUM, check stats
# - No custom tools needed—standard PostgreSQL ecosystem

Developer Access via psql:

# Developer debugging on Windows/Mac
psql -h localhost -p 5432 -U healthapp -d healthrecords

healthrecords=# \dt
              List of relations
 Schema |     Name     | Type  |  Owner
--------+--------------+-------+----------
 public | patients     | table | healthapp
 public | visits       | table | healthapp
 public | prescriptions| table | healthapp

healthrecords=# SELECT COUNT(*) FROM patients;
 count
-------
  1523
(1 row)

healthrecords=# EXPLAIN ANALYZE SELECT * FROM patients WHERE mrn = 'MRN001234';
-- Works identically to PostgreSQL

Adoption Strategy

Phase 1: Proof of Concept (Weeks 1-2)

Target: Validate PostgreSQL protocol compatibility with existing application

Tactics:

  • Connect Existing Client: Point psql or pgAdmin to HeliosDB Lite on localhost:5432
   psql -h localhost -p 5432 -U myapp -d test
  • Run Simple Queries: Execute basic SELECT/INSERT/UPDATE to verify protocol
  • Test Existing Application: Change connection string, run integration tests
  • Benchmark Performance: Compare latency vs cloud PostgreSQL

Deliverable: Internal POC report with performance comparison

Phase 2: Pilot Deployment (Weeks 3-8)

Tactics:

  • Migrate Low-Risk Service: Start with read-heavy or non-critical microservice
  • Export data: pg_dump postgres://prod-db/service | psql -h localhost/heliosdb
  • Switch connection string in config
  • Monitor for protocol errors, performance regression
  • Deploy to Edge Subset: Roll out to 10-50 edge devices with monitoring
  • Validate ORMs: Test Prisma/SQLAlchemy/Hibernate migrations and queries
  • Measure Business Impact: Track infrastructure cost reduction, latency improvements

Risk Mitigation:

  • Keep PostgreSQL connection string in config for fast rollback
  • Automated alerts for protocol errors or performance degradation

Phase 3: Full Rollout (Weeks 9-24)

Target: Organization-wide adoption for compatible workloads

Tactics:

  • Tenant-by-Tenant Migration (SaaS):
  • Validate data integrity (checksum comparison)
  • Gradually increase to large tenants
  • Microservice Migration (Enterprise):
  • Automate deployment with Helm charts/Terraform
  • Update CI/CD to use HeliosDB Lite for tests
  • Edge Fleet Deployment (IoT):
  • Containerize HeliosDB Lite with app (Docker/Kubernetes)
  • Deploy via fleet management (AWS IoT Greengrass, Balena)
  • Implement cloud sync for edge data aggregation
  • Team Training:
  • Document connection string changes
  • Share migration runbooks
  • Highlight "no code changes" to reduce friction

Long-Term Governance:

  • Quarterly reviews of cost savings and performance

Conclusion

Yet this ecosystem has been locked to server-class deployments, forcing teams to abandon PostgreSQL expertise when workloads shrink below cloud database minimums or move to edge/embedded environments. SQLite and DuckDB offer lightweight alternatives but require complete application rewrites, break tool compatibility, and waste accumulated PostgreSQL knowledge.

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