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
| Type | Env Variable | Notes |
|---|---|---|
mongodb | MONGODB_URI | Recommended for most services |
redis | REDIS_URL | Use for caching and queues |
neo4j | NEO4J_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.
// 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!),
)
MongoDB databases are named {service}-{environment} by default:
| Service | Env | Database |
|---|---|---|
| my-api | sandbox | my-api-sandbox |
| my-api | prod | my-api-prod |
Override with a custom name:
spec:
databases:
- type: mongodb
name: shared-data # uses "shared-data" instead of "{service}-{env}"
# .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
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).
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
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
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
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 importover rawmongoimport— no flags to remember, types are handled automatically.
# 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.
# ❌ 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