Skip to content

Runtime Profile Comparison

CAP supports multiple database backends via profiles. The same service code runs unchanged — only persistence configuration and model extensions differ.

Quick Reference

Featuresqlite (dev)hybrid (HANA + local)pg (PostgreSQL)production (HANA)
Start commandnpm run sqlitenpm run watchnpm run pgcds-serve
DatabaseSQLite (local file)SAP HANA HDI containerPostgreSQLSAP HANA HDI container
CredentialsNone neededBTP service binding.env fileBTP service binding
External servicesMockedReal (Alert Notification, etc.)MockedReal
Profile CDS loadeddb/sqlite/index.cdsdb/hana/index.cdsdb/postgres/index.cdsdb/hana/index.cds
Schema journalIgnoredActive (@cds.persistence.journal)IgnoredActive
MultitenancyNot applicableOptionalNot applicableSupported
Best forUnit tests, fast iterationIntegration testingPostgreSQL-specific workBTP deployment

What changes between profiles

Database features

FeatureSQLiteHANAPostgreSQL
UUID generationCAP generatesHANA nativeCAP generates
Case sensitivityCase-insensitiveCase-insensitiveCase-sensitive by default
Regex in SQLNot supportedNot supported~ operator
Full-text searchLimitedHANA full-texttsvector
Schema migrationsRecreate@cds.persistence.journalRecreate
Concurrent accessSingle writerFully concurrentFully concurrent
Connection poolSingle fileHDI containerpg pool

What stays the same (CAP portability guarantee)

  • All CDS entity/service definitions
  • All handler code (before/on/after)
  • All OData, REST, GraphQL endpoints
  • All authorization annotations
  • All tests (using SQLite in-memory for speed)

Profile-specific CDS extensions

db/hana/index.cds — adds HANA-native features:

cds
using from '../schema';
// HANA-specific: activate schema evolution journal
// Profile selection: CDS only loads this when profile=hana or profile=hybrid

db/sqlite/index.cds — minimal, just pulls in base schema:

cds
using from '../schema';
// SQLite has no special extensions needed for this sample

db/postgres/index.cds — PostgreSQL extensions:

cds
using from '../schema';
// PostgreSQL-specific: adjust any behavior here

Switching profiles

bash
# Development (SQLite, no external services)
npm run sqlite

# Integration testing with HANA (requires HDI container binding)
npm run watch        # hybrid profile

# PostgreSQL (requires .env with PG credentials)
npm run pg

# Deploy to HANA
npm run hana         # creates HDI container and deploys schema

# Load fixture data (pick the right profile)
npm run load_sqlite  # SQLite
npm run load         # hybrid/HANA
npm run load_pg      # PostgreSQL

Profile configuration in package.json

CAP reads profile config from package.json under cds:

json
{
  "cds": {
    "requires": {
      "db": "sqlite"
    },
    "[sqlite]": {
      "requires": {
        "db": { "kind": "sqlite", "credentials": { "url": "db.sqlite" } }
      }
    },
    "[hybrid]": {
      "requires": {
        "db": { "kind": "hana" }
      }
    }
  }
}

The [profile] blocks override the base requires when --profile <name> is passed.

Testing across profiles

All automated tests run against SQLite in-memory regardless of profile, which means:

  • Fast test execution (no external service needed)
  • Complete isolation between test runs
  • No test data left in a real database

The test runner sets CDS_ENV=sqlite and CDS_REQUIRES_DB_CREDENTIALS_URL=:memory: before loading CDS.

To verify HANA-specific behavior, you must run integration tests against a real HDI container:

bash
npm run watch   # start in hybrid mode first
# then run specific integration test scripts