Databases on Tawa

The Short Version

Declare databases in catalog-info.yaml. The builder provisions connection strings and injects them as environment variables. Your code reads from process.env. Identical across all environments.

spec:
  databases:
    - type: mongodb   # → MONGODB_URI
    - type: redis     # → REDIS_URL
    - type: neo4j     # → NEO4J_URI

Supported Types

TypeEnv VariableNotes
mongodbMONGODB_URIRecommended for most services
redisREDIS_URLUse for caching and queues
neo4jNEO4J_URI (plus NEO4J_USERNAME and NEO4J_PASSWORD)Use for graph data

Only these three types are provisioned. Any other type (such as postgres, mariadb, or sqlite) is logged as a warning and skipped — the build still completes successfully. That database simply isn't provisioned, so its env var is never injected.

Connecting

// MongoDB
import mongoose from 'mongoose'
const uri = process.env.MONGODB_URI
if (!uri) throw new Error('MONGODB_URI not configured')
await mongoose.connect(uri)

// Redis
import Redis from 'ioredis'
const url = process.env.REDIS_URL
if (!url) throw new Error('REDIS_URL not configured')
const redis = new Redis(url)

// Neo4j — NEO4J_URI, NEO4J_USERNAME, and NEO4J_PASSWORD are all injected
import neo4j from 'neo4j-driver'
const uri = process.env.NEO4J_URI
if (!uri) throw new Error('NEO4J_URI not configured')
const driver = neo4j.driver(
  uri,
  neo4j.auth.basic(process.env.NEO4J_USERNAME!, process.env.NEO4J_PASSWORD!),
)

Database Naming

MongoDB databases are named {service}-{environment} by default:

ServiceEnvDatabase
my-apisandboxmy-api-sandbox
my-apiprodmy-api-prod

Override with a custom name:

spec:
  databases:
    - type: mongodb
      name: shared-data   # uses "shared-data" instead of "{service}-{env}"

Local Development

# .env.local
MONGODB_URI=mongodb://localhost:27017/my-api-dev
REDIS_URL=redis://localhost:6379/0
NEO4J_URI=bolt://localhost:7687

Or use tawa config pull to get the sandbox connection strings:

tawa config pull  # writes to .env.local

Vault (Dynamic Credentials)

MongoDB credentials are rotated automatically via HashiCorp Vault. The Vault Agent sidecar handles credential injection — your code reads MONGODB_URI as always, but the underlying credentials rotate without a redeploy.

Redis and Neo4j Vault rotation is pending (Phase 2c/2d).

Shared Databases (catalog 0.5.0+)

Services can share databases. The owning service declares sharedWith, the consumer declares consumesDatabase:

# Owning service (analytics-api):
spec:
  databases:
    - type: mongodb
      sharedWith: [reporting-service]

# Consuming service (reporting-service):
spec:
  consumesDatabase:
    - from: analytics-api
      type: mongodb   # → MONGODB_URI_ANALYTICS_API env var

Accessing Data in Running Services

Platform databases are not reachable from localhost. Use the koko CLI — it proxies all operations through the Koko API with authentication and safety controls.

# Install once
npm install -g koko-db

# Authenticate (shares tawa login session)
tawa login

Read Data

koko query products -s my-api -e prod --filter '{"active":true}' --limit 20
koko sample users   -s my-api -e prod --limit 5
koko stats          -s my-api -e prod
koko collections    -s my-api -e prod

Export / Import (EJSON — type-safe)

koko export outputs EJSON format: ObjectIds are preserved as {"$oid":"..."} and Dates as {"$date":"..."}. This means exports can be re-imported without ObjectId type corruption.

# Export prod → local file
koko export products -s my-api -e prod -o /tmp/products.ndjson

# Import into sandbox (koko import handles EJSON natively)
koko import products -s my-api -e sandbox -i /tmp/products.ndjson --upsert

# Import into local MongoDB (requires --legacy flag for $oid markers)
mongoimport --db my-api-dev --collection products --file /tmp/products.ndjson --legacy

Always use koko import over raw mongoimport — no flags to remember, types are handled automatically.

Copy Between Environments

# Direct server-side copy — fastest, no download
koko copy products --service my-api --from prod --to sandbox

See tawa-docs/conventions/koko-data-access.md for the full quickstart.

What NOT to Do

# ❌ WRONG: unsupported types — silently skipped (warning, non-fatal)
spec:
  databases:
    - type: postgres   # not provisioned — logged as a warning and skipped
    - type: mariadb    # not provisioned — logged as a warning and skipped

# ❌ WRONG: hardcoding connection strings
MONGODB_URI=mongodb://prod-host:27017/mydb  # in tawa config — let builder provision it

# ✅ CORRECT: declare in catalog, let builder provision
spec:
  databases:
    - type: mongodb

Last updated: July 15, 2026