superapp
Backend

Databases

Connect to any database through DuckDB.

Every database in @superapp/backend is accessed through a provider -- a thin adapter that tells DuckDB how to attach and query the source.

import { createEngine } from '@superapp/backend'
import { postgresProvider } from '@superapp/backend/integrations/postgres'

const engine = createEngine({
  integrations: [postgresProvider],
  connections: {
    main: { type: 'postgres', url: process.env.PG_URL! },
  },
})

Native vs Custom Providers

Native providers use DuckDB's built-in ATTACH extensions. DuckDB handles the wire protocol directly, which means full SQL pushdown and maximum performance. Postgres, MySQL, SQLite, and CSV are all native.

Custom providers implement a CustomIntegrationProvider interface for sources DuckDB cannot attach natively -- REST APIs, GraphQL endpoints, edge runtimes, or proprietary databases. Queries are translated into provider-specific calls and results are returned as virtual tables.

Built-in Providers

ProviderImportReadWriteTransport
PostgreSQL@superapp/backend/integrations/postgresYesYesNative (postgres_scanner)
MySQL@superapp/backend/integrations/mysqlYesYesNative (mysql_scanner)
SQLite@superapp/backend/integrations/sqliteYesYesNative (sqlite_scanner)
CSV@superapp/backend/integrations/csvYesNoNative (read_csv_auto)

Provider Interface

Every native provider exports a single object that satisfies the IntegrationProvider interface:

interface IntegrationProvider {
  type: string
  attachSQL: (name: string, config: ConnectionConfig) => string
  detachSQL: (name: string) => string
  introspect: (name: string) => Promise<TableSchema[]>
  capabilities: {
    read: boolean
    write: boolean
    transactions: boolean
  }
}

The attachSQL method returns the DuckDB ATTACH statement for the given connection config. The engine calls it once on startup (or when a connection is added via the admin UI) and caches the result for the lifetime of the process.

Registering Multiple Providers

Pass all providers you need in the integrations array. Only connections whose type matches a registered provider will be attached:

import { postgresProvider } from '@superapp/backend/integrations/postgres'
import { mysqlProvider } from '@superapp/backend/integrations/mysql'
import { csvProvider } from '@superapp/backend/integrations/csv'

const engine = createEngine({
  integrations: [postgresProvider, mysqlProvider, csvProvider],
  connections: {
    main: { type: 'postgres', url: process.env.PG_URL! },
    warehouse: { type: 'mysql', url: process.env.MYSQL_URL! },
    reports: { type: 'csv', path: './data/reports' },
  },
})

Next Steps

On this page