Backend Setup
TypeGraph stores graph data in your existing relational database using Drizzle ORM adapters. This guide covers setting up SQLite and PostgreSQL backends.
SQLite
Section titled “SQLite”SQLite is ideal for development, testing, single-server deployments, and embedded applications.
Quick Setup
Section titled “Quick Setup”For development and testing, use the convenience function that handles everything:
import { createLocalSqliteBackend } from "@nicia-ai/typegraph/sqlite/local";import { createStore } from "@nicia-ai/typegraph";
// In-memory database (resets on restart)const { backend } = createLocalSqliteBackend();const store = createStore(graph, backend);
// File-based database (persisted)const { backend, db } = createLocalSqliteBackend({ path: "./app.db" });const store = createStore(graph, backend);Manual Setup
Section titled “Manual Setup”For full control over the database connection:
import Database from "better-sqlite3";import { drizzle } from "drizzle-orm/better-sqlite3";import { createSqliteBackend, generateSqliteMigrationSQL } from "@nicia-ai/typegraph/sqlite";import { createStore } from "@nicia-ai/typegraph";
// Create and configure the databaseconst sqlite = new Database("app.db");sqlite.pragma("journal_mode = WAL"); // Recommended for performancesqlite.pragma("foreign_keys = ON");
// Run TypeGraph migrationssqlite.exec(generateSqliteMigrationSQL());
// Create Drizzle instance and backendconst db = drizzle(sqlite);const backend = createSqliteBackend(db);const store = createStore(graph, backend);
// Clean up when doneprocess.on("exit", () => sqlite.close());SQLite with Vector Search
Section titled “SQLite with Vector Search”For semantic search, use sqlite-vec:
import Database from "better-sqlite3";import { drizzle } from "drizzle-orm/better-sqlite3";import { createSqliteBackend, generateSqliteMigrationSQL } from "@nicia-ai/typegraph/sqlite";
const sqlite = new Database("app.db");
// Load sqlite-vec extensionsqlite.loadExtension("vec0");
// Run migrations (includes vector index setup)sqlite.exec(generateSqliteMigrationSQL());
const db = drizzle(sqlite);const backend = createSqliteBackend(db);See Semantic Search for query examples.
API Reference
Section titled “API Reference”createLocalSqliteBackend(options?)
Section titled “createLocalSqliteBackend(options?)”Creates a SQLite backend with automatic database and schema setup.
function createLocalSqliteBackend(options?: { path?: string; // Database path, defaults to ":memory:" tables?: SqliteTables;}): { backend: GraphBackend; db: BetterSQLite3Database };createSqliteBackend(db, options?)
Section titled “createSqliteBackend(db, options?)”Creates a SQLite backend from an existing Drizzle database instance.
function createSqliteBackend( db: BetterSQLite3Database, options?: { tables?: SqliteTables }): GraphBackend;generateSqliteMigrationSQL()
Section titled “generateSqliteMigrationSQL()”Returns SQL for creating TypeGraph tables in SQLite.
function generateSqliteMigrationSQL(): string;PostgreSQL
Section titled “PostgreSQL”PostgreSQL is recommended for production deployments with concurrent access, large datasets, or when you need advanced features like pgvector.
Basic Setup
Section titled “Basic Setup”import { Pool } from "pg";import { drizzle } from "drizzle-orm/node-postgres";import { createPostgresBackend, generatePostgresMigrationSQL } from "@nicia-ai/typegraph/postgres";import { createStore } from "@nicia-ai/typegraph";
// Create connection poolconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, // Maximum connections});
// Run TypeGraph migrationsawait pool.query(generatePostgresMigrationSQL());
// Create Drizzle instance and backendconst db = drizzle(pool);const backend = createPostgresBackend(db);const store = createStore(graph, backend);PostgreSQL with Vector Search
Section titled “PostgreSQL with Vector Search”For semantic search, enable pgvector:
import { Pool } from "pg";import { drizzle } from "drizzle-orm/node-postgres";import { createPostgresBackend, generatePostgresMigrationSQL } from "@nicia-ai/typegraph/postgres";
const pool = new Pool({ connectionString: process.env.DATABASE_URL });
// Migration SQL includes pgvector extensionawait pool.query(generatePostgresMigrationSQL());// Runs: CREATE EXTENSION IF NOT EXISTS vector;
const db = drizzle(pool);const backend = createPostgresBackend(db);See Semantic Search for query examples.
Connection Pooling
Section titled “Connection Pooling”For production, always use connection pooling:
import { Pool } from "pg";
const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, // Maximum pool size idleTimeoutMillis: 30000, // Close idle connections after 30s connectionTimeoutMillis: 2000, // Timeout for new connections});
// Handle pool errorspool.on("error", (err) => { console.error("Unexpected pool error", err);});
// Graceful shutdownprocess.on("SIGTERM", async () => { await pool.end(); process.exit(0);});API Reference
Section titled “API Reference”createPostgresBackend(db, options?)
Section titled “createPostgresBackend(db, options?)”Creates a PostgreSQL backend adapter.
function createPostgresBackend( db: NodePgDatabase, options?: { tables?: PostgresTables }): GraphBackend;generatePostgresMigrationSQL()
Section titled “generatePostgresMigrationSQL()”Returns SQL for creating TypeGraph tables in PostgreSQL, including the pgvector extension.
function generatePostgresMigrationSQL(): string;generatePostgresDDL(tables?)
Section titled “generatePostgresDDL(tables?)”Returns individual DDL statements (CREATE TABLE, CREATE INDEX) as an array. Useful when you need per-statement control, for example to execute them in separate transactions or log them individually.
function generatePostgresDDL(tables?: PostgresTables): string[];Drizzle Entrypoints
Section titled “Drizzle Entrypoints”TypeGraph exposes Drizzle adapters through two public entrypoints:
@nicia-ai/typegraph/sqlite- SQLite adapter exports@nicia-ai/typegraph/postgres- PostgreSQL adapter exports
Import from the entrypoint matching your database:
import { createSqliteBackend, tables } from "@nicia-ai/typegraph/sqlite";import { createPostgresBackend, tables } from "@nicia-ai/typegraph/postgres";Cloudflare D1
Section titled “Cloudflare D1”TypeGraph supports Cloudflare D1 for edge deployments, with some limitations.
import { drizzle } from "drizzle-orm/d1";import { createStore } from "@nicia-ai/typegraph";import { createSqliteBackend } from "@nicia-ai/typegraph/sqlite";
export default { async fetch(request: Request, env: Env) { const db = drizzle(env.DB); const backend = createSqliteBackend(db); const store = createStore(graph, backend);
// Use store... },};Important: D1 does not support transactions. See Limitations for details.
Backend Capabilities
Section titled “Backend Capabilities”Check what features a backend supports:
const backend = createSqliteBackend(db);
if (backend.capabilities.transactions) { await store.transaction(async (tx) => { /* ... */ });} else { // Handle non-transactional execution}
if (backend.capabilities.vectorSearch) { // Vector similarity queries available}Connection Management
Section titled “Connection Management”TypeGraph does not manage database connections. You are responsible for:
- Creating connections with appropriate configuration
- Connection pooling for production use
- Closing connections on shutdown
// You create the connectionconst sqlite = new Database("app.db");const db = drizzle(sqlite);const backend = createSqliteBackend(db);const store = createStore(graph, backend);
// You close the connectionprocess.on("exit", () => { sqlite.close();});The store.close() method is a no-op—cleanup is your responsibility.
Environment-Specific Setup
Section titled “Environment-Specific Setup”Development
Section titled “Development”// In-memory for fast testsconst { backend } = createLocalSqliteBackend();
// Or file-based for persistence during developmentconst { backend } = createLocalSqliteBackend({ path: "./dev.db" });Testing
Section titled “Testing”// Fresh in-memory database per testbeforeEach(() => { const { backend } = createLocalSqliteBackend(); store = createStore(graph, backend);});Production
Section titled “Production”// PostgreSQL with poolingconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, ssl: { rejectUnauthorized: false }, // For managed databases});
await pool.query(generatePostgresMigrationSQL());const db = drizzle(pool);const backend = createPostgresBackend(db);const [store] = await createStoreWithSchema(graph, backend);Next Steps
Section titled “Next Steps”- Schemas & Types - Define your graph schema
- Semantic Search - Vector embeddings and similarity search
- Limitations - Backend-specific constraints