Files
cmdb-insight/docs/DATABASE-RECOMMENDATION.md
Bert Hausmans a7f8301196 Add database adapter system, production deployment configs, and new dashboard components
- Add PostgreSQL and SQLite database adapters with factory pattern
- Add migration script for SQLite to PostgreSQL
- Add production Dockerfiles and docker-compose configs
- Add deployment documentation and scripts
- Add BIA sync dashboard and matching service
- Add data completeness configuration and components
- Add new dashboard components (BusinessImportanceComparison, ComplexityDynamics, etc.)
- Update various services and routes
- Remove deprecated management-parameters.json and taxonomy files
2026-01-14 00:38:40 +01:00

12 KiB

Database Engine Aanbeveling - Azure Productie

Huidige Situatie

De applicatie gebruikt momenteel SQLite via better-sqlite3:

  • cmdb-cache.db: ~20MB - CMDB object cache
  • classifications.db: Classification history

Aanbeveling: PostgreSQL

Belangrijk: Azure Database for MariaDB wordt afgeschaft (retirement september 2025).
De keuze is daarom tussen PostgreSQL en MySQL (niet MariaDB).

PostgreSQL vs MySQL Vergelijking

Feature PostgreSQL MySQL (Azure)
Azure Support Flexible Server Flexible Server
Kosten (B1ms) ~€20-30/maand ~€20-30/maand
JSON Support JSONB (superieur) JSON (basis)
Performance Uitstekend Goed
Concurrency MVCC (zeer goed) Goed
SQL Standards Zeer compliant ⚠️ Eigen dialect
Full-Text Search Ingebouwd ⚠️ Basis
Community Groot & actief Groot & actief
Development Tools Uitstekend Goed

Voor jouw use case (JSON data, 20 gebruikers):

PostgreSQL heeft voordeel:

  • JSONB: Betere JSON performance en querying (gebruikt in huidige schema)
  • MVCC: Betere concurrency voor 20 gelijktijdige gebruikers
  • SQL Standards: Makkelijker migreren van SQLite
  • Full-Text Search: Ingebouwd (handig voor toekomstige zoekfuncties)

MySQL is ook goed:

  • Vergelijkbare kosten
  • Goede performance
  • Veel gebruikt (bekende technologie)

Conclusie: Beide zijn goede keuzes. PostgreSQL heeft lichte voordelen voor JSON-heavy workloads en betere SQLite compatibiliteit.

Waarom PostgreSQL?

Identieke Dev/Prod Stack

  • Lokaal: PostgreSQL via Docker (gratis)
  • Azure: Azure Database for PostgreSQL Flexible Server
  • Zelfde database engine, zelfde SQL syntax

Azure Integratie

  • Native ondersteuning in Azure
  • Managed service (geen server management)
  • Betaalbaar: Basic tier ~€20-30/maand voor 20 gebruikers

Performance

  • Betere concurrency dan SQLite (20 gebruikers)
  • Connection pooling (nodig voor web apps)
  • Betere query performance bij groei

Features

  • JSON support (gebruikt in huidige schema)
  • Transactions
  • Foreign keys
  • Full-text search (toekomstig)

Development Experience

  • Docker setup identiek aan productie
  • Migraties mogelijk (Prisma, Knex, etc.)
  • Betere tooling

Alternatief: SQLite Blijven

Voordelen:

  • Geen migratie nodig
  • Werkt in Azure App Service (file storage)
  • Gratis
  • Eenvoudig

Nadelen:

  • Beperkte concurrency (kan problemen geven met 20 gebruikers)
  • Geen connection pooling
  • File-based (moeilijker backup/restore)
  • Beperkte query performance bij groei

Conclusie: SQLite kan werken voor 20 gebruikers, maar PostgreSQL is beter voor productie.


Migratie naar PostgreSQL

Stappenplan

1. Database Abstraction Layer

Maak een database abstraction layer zodat we kunnen wisselen tussen SQLite (dev) en PostgreSQL (prod):

// backend/src/services/database/interface.ts
export interface DatabaseAdapter {
  query(sql: string, params?: any[]): Promise<any[]>;
  execute(sql: string, params?: any[]): Promise<void>;
  transaction<T>(callback: (db: DatabaseAdapter) => Promise<T>): Promise<T>;
  close(): Promise<void>;
}

2. PostgreSQL Adapter

// backend/src/services/database/postgresAdapter.ts
import { Pool } from 'pg';

export class PostgresAdapter implements DatabaseAdapter {
  private pool: Pool;

  constructor(connectionString: string) {
    this.pool = new Pool({ connectionString });
  }

  async query(sql: string, params?: any[]): Promise<any[]> {
    const result = await this.pool.query(sql, params);
    return result.rows;
  }

  // ... implement other methods
}

3. SQLite Adapter (voor backward compatibility)

// backend/src/services/database/sqliteAdapter.ts
import Database from 'better-sqlite3';

export class SqliteAdapter implements DatabaseAdapter {
  private db: Database.Database;

  constructor(dbPath: string) {
    this.db = new Database(dbPath);
  }

  async query(sql: string, params?: any[]): Promise<any[]> {
    const stmt = this.db.prepare(sql);
    return stmt.all(...(params || [])) as any[];
  }

  // ... implement other methods
}

4. Schema Migratie

SQLite → PostgreSQL verschillen:

  • INTEGER PRIMARY KEY AUTOINCREMENTSERIAL PRIMARY KEY
  • TEXTTEXT of VARCHAR
  • JSONJSONB (beter in PostgreSQL)
  • ON CONFLICTON CONFLICT (werkt in beide)

SQLite → MySQL verschillen:

  • INTEGER PRIMARY KEY AUTOINCREMENTINT AUTO_INCREMENT PRIMARY KEY
  • TEXTTEXT of VARCHAR(255)
  • JSONJSON (basis support)
  • ON CONFLICTON DUPLICATE KEY UPDATE (andere syntax)

Azure Setup

Optie 1: Azure Database for PostgreSQL Flexible Server

Basic Tier (aanbevolen voor 20 gebruikers):

  • Burstable B1ms: 1 vCore, 2GB RAM
  • Storage: 32GB (meer dan genoeg voor 20MB database)
  • Kosten: ~€20-30/maand
  • Backup: 7 dagen retention (gratis)

Configuratie:

# Azure CLI
az postgres flexible-server create \
  --resource-group rg-cmdb-gui \
  --name psql-cmdb-gui \
  --location westeurope \
  --admin-user cmdbadmin \
  --admin-password <secure-password> \
  --sku-name Standard_B1ms \
  --tier Burstable \
  --storage-size 32 \
  --version 15

Connection String:

postgresql://cmdbadmin:<password>@psql-cmdb-gui.postgres.database.azure.com:5432/cmdb?sslmode=require

Optie 2: Azure Database for MySQL Flexible Server

Basic Tier (aanbevolen voor 20 gebruikers):

  • Burstable B1ms: 1 vCore, 2GB RAM
  • Storage: 32GB (meer dan genoeg voor 20MB database)
  • Kosten: ~€20-30/maand
  • Backup: 7 dagen retention (gratis)

Configuratie:

# Azure CLI
az mysql flexible-server create \
  --resource-group rg-cmdb-gui \
  --name mysql-cmdb-gui \
  --location westeurope \
  --admin-user cmdbadmin \
  --admin-password <secure-password> \
  --sku-name Standard_B1ms \
  --tier Burstable \
  --storage-size 32 \
  --version 8.0.21

Connection String:

mysql://cmdbadmin:<password>@mysql-cmdb-gui.mysql.database.azure.com:3306/cmdb?ssl-mode=REQUIRED

MySQL vs PostgreSQL voor jouw schema:

  • JSON: MySQL heeft JSON type, maar PostgreSQL JSONB is sneller voor queries
  • AUTOINCREMENT: MySQL gebruikt AUTO_INCREMENT, PostgreSQL gebruikt SERIAL (beide werken)
  • ON CONFLICT: MySQL gebruikt ON DUPLICATE KEY UPDATE, PostgreSQL gebruikt ON CONFLICT (beide werken)

Local Development Setup

Optie 1: Docker Compose voor PostgreSQL

Voeg toe aan docker-compose.yml:

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: cmdb
      POSTGRES_USER: cmdb
      POSTGRES_PASSWORD: cmdb-dev
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U cmdb"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  postgres_data:

Optie 2: Docker Compose voor MySQL

Voeg toe aan docker-compose.yml:

services:
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: cmdb
      MYSQL_USER: cmdb
      MYSQL_PASSWORD: cmdb-dev
      MYSQL_ROOT_PASSWORD: root-dev
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  mysql_data:

Environment variabelen (lokaal - PostgreSQL):

# .env.local
DATABASE_URL=postgresql://cmdb:cmdb-dev@localhost:5432/cmdb
# of
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_NAME=cmdb
DATABASE_USER=cmdb
DATABASE_PASSWORD=cmdb-dev

Environment variabelen (Azure):

# Azure App Service Configuration
DATABASE_TYPE=postgres
DATABASE_HOST=psql-cmdb-gui.postgres.database.azure.com
DATABASE_PORT=5432
DATABASE_NAME=cmdb
DATABASE_USER=cmdbadmin
DATABASE_PASSWORD=<from-key-vault>
DATABASE_SSL=true

Environment variabelen (lokaal - MySQL):

# .env.local
DATABASE_URL=mysql://cmdb:cmdb-dev@localhost:3306/cmdb
# of
DATABASE_TYPE=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_NAME=cmdb
DATABASE_USER=cmdb
DATABASE_PASSWORD=cmdb-dev

Environment variabelen (Azure - MySQL):

# Azure App Service Configuration
DATABASE_TYPE=mysql
DATABASE_HOST=mysql-cmdb-gui.mysql.database.azure.com
DATABASE_PORT=3306
DATABASE_NAME=cmdb
DATABASE_USER=cmdbadmin
DATABASE_PASSWORD=<from-key-vault>
DATABASE_SSL=true

Kosten Vergelijking

Optie Lokaal Azure (maandelijks) Totaal
PostgreSQL Gratis (Docker) €20-30 €20-30
MySQL Gratis (Docker) €20-30 €20-30
SQLite Gratis €0 (in App Service) €0
Azure SQL SQL Server Express €50-100 €50-100

Aanbeveling: PostgreSQL - beste balans tussen kosten, performance en identieke stack.
MySQL is ook een goede keuze met vergelijkbare kosten en performance.


Migratie Script

SQLite naar PostgreSQL Converter

// scripts/migrate-sqlite-to-postgres.ts
import Database from 'better-sqlite3';
import { Pool } from 'pg';

async function migrate() {
  // Connect to SQLite
  const sqlite = new Database('./data/cmdb-cache.db');
  
  // Connect to PostgreSQL
  const pg = new Pool({
    connectionString: process.env.DATABASE_URL
  });

  // Migrate cached_objects
  const objects = sqlite.prepare('SELECT * FROM cached_objects').all();
  for (const obj of objects) {
    await pg.query(
      `INSERT INTO cached_objects (id, object_key, object_type, label, data, jira_updated_at, jira_created_at, cached_at)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
       ON CONFLICT (id) DO NOTHING`,
      [obj.id, obj.object_key, obj.object_type, obj.label, obj.data, obj.jira_updated_at, obj.jira_created_at, obj.cached_at]
    );
  }

  // Migrate relations, metadata, etc.
  // ...

  sqlite.close();
  await pg.end();
}

Implementatie Plan

Fase 1: Database Abstraction (1-2 dagen)

  1. Maak DatabaseAdapter interface
  2. Implementeer PostgresAdapter en SqliteAdapter
  3. Update CacheStore en DatabaseService om adapter te gebruiken

Fase 2: Local PostgreSQL Setup (0.5 dag)

  1. Voeg PostgreSQL toe aan docker-compose.yml
  2. Test lokaal met PostgreSQL
  3. Update environment configuratie

Fase 3: Schema Migratie (1 dag)

  1. Converteer SQLite schema naar PostgreSQL
  2. Maak migratie script
  3. Test migratie lokaal

Fase 4: Azure Setup (1 dag)

  1. Maak Azure Database for PostgreSQL
  2. Configureer connection string in Key Vault
  3. Test connectiviteit

Fase 5: Productie Migratie (0.5 dag)

  1. Migreer data van SQLite naar PostgreSQL
  2. Update App Service configuratie
  3. Test in productie

Totaal: ~3-4 dagen werk


Aanbeveling

🏆 PostgreSQL (Aanbevolen)

Gebruik PostgreSQL voor:

  • Identieke dev/prod stack
  • Betere JSON performance (JSONB)
  • Betere concurrency (MVCC)
  • Azure native ondersteuning
  • Toekomstbestendig
  • Betaalbaar (~€20-30/maand)
  • Makkelijker migratie van SQLite (SQL syntax)

MySQL (Ook goed)

MySQL is ook een goede keuze als:

  • Je team meer ervaring heeft met MySQL
  • Je voorkeur geeft aan MySQL ecosystem
  • Vergelijkbare kosten en performance acceptabel zijn
  • Je JSON queries niet te complex zijn

Nadelen t.o.v. PostgreSQL:

  • ⚠️ Minder geavanceerde JSON support (geen JSONB)
  • ⚠️ Minder SQL standards compliant
  • ⚠️ Iets andere syntax voor conflicten

💰 SQLite (Minimale kosten)

SQLite blijft optie als:

  • Je snel moet deployen zonder migratie
  • Kosten kritiek zijn (€0 vs €20-30)
  • Je accepteert beperkingen (concurrency, performance)

Conclusie: Voor jouw use case (JSON data, 20 gebruikers) is PostgreSQL de beste keuze, maar MySQL is ook prima. Beide zijn veel beter dan SQLite voor productie.


Next Steps

  1. Beslissing: PostgreSQL of SQLite blijven?
  2. Als PostgreSQL: Start met Fase 1 (Database Abstraction)
  3. Als SQLite: Documenteer beperkingen en overweeg toekomstige migratie