Platform databases (MongoDB, Redis, Neo4j) run inside the Kubernetes cluster and are not reachable from localhost. The koko CLI proxies all operations through the Koko API — authenticated, read-safe, and type-preserving.
# Install
npm install -g koko-db
# Authenticate (shares your tawa login session — run tawa login first)
tawa login
koko --version # should be 0.5.0+
Never use curl, kubectl port-forward, or raw API calls to access databases.
| Wrong | Right |
|---|---|
curl http://localhost:3001/api/db/... | koko query users -s my-api -e prod |
kubectl port-forward ... && mongosh | koko copy users --from prod --to sandbox |
| Direct MongoDB connection strings | koko export → koko import |
The koko CLI handles auth, safety guards, EJSON type preservation, and pagination automatically.
koko resolves your service name automatically from the project directory. You can also pass it explicitly:
# From inside a service directory (reads catalog-info.yaml or .tawa.yaml)
koko query products -e prod
# Explicit service name
koko query products -s fairshare-cms -e prod
# List databases provisioned for a service
koko databases -s my-api
# Collection stats
koko stats -s my-api -e prod
koko collections -s my-api -e prod
# Sample a few documents (random)
koko sample orders -s my-api -e prod --limit 5
# Find with filter
koko query users -s my-api -e prod \
--filter '{"status":"active"}' \
--limit 20 \
--sort '{"createdAt":-1}'
# With projection
koko query products -s my-api -e prod \
--filter '{"active":true}' \
--projection '{"name":1,"slug":1,"tiers":1}'
# Aggregate
koko query orders -s my-api -e prod \
--aggregate '[{"$group":{"_id":"$paymentStatus","count":{"$sum":1}}}]'
# JSON output (for piping/scripting)
koko query users -s my-api -e prod --filter '{"email":"[email protected]"}' --json
koko export outputs EJSON (MongoDB Extended JSON). ObjectIds are serialized as {"$oid":"..."} and Dates as {"$date":"..."} — not plain strings. This means the NDJSON file can be re-imported with correct BSON types and no corruption.
# Export a collection to file
koko export products -s my-api -e prod -o /tmp/products.ndjson
# Export with a filter
koko export orders -s my-api -e prod \
--filter '{"createdAt":{"$gte":"2026-01-01"}}' \
-o /tmp/recent-orders.ndjson
Import via koko import — EJSON is handled natively, no flags needed:
koko import products -s my-api -e sandbox -i /tmp/products.ndjson --upsert
If you must use mongoimport (into local MongoDB), add --legacy so it recognises $oid/$date markers:
mongoimport --db my-api-dev --collection products \
--file /tmp/products.ndjson --legacy
Prefer
koko importovermongoimport— no flags to remember, round-trip is always correct.
Server-side copy — no download, no EJSON conversion, fastest option:
# Preview count first
koko copy products -s my-api --from prod --to sandbox --dry-run
# Execute
koko copy products -s my-api --from prod --to sandbox
When you need your local MongoDB to exactly match production:
# Step 1: Export all collections from prod
koko export products -s my-api -e prod -o /tmp/products.ndjson
koko export users -s my-api -e prod -o /tmp/users.ndjson
koko export orders -s my-api -e prod -o /tmp/orders.ndjson
# Step 2: Import into local MongoDB (--legacy handles $oid/$date markers)
mongoimport --db my-api-dev --collection products --file /tmp/products.ndjson --legacy --drop
mongoimport --db my-api-dev --collection users --file /tmp/users.ndjson --legacy --drop
mongoimport --db my-api-dev --collection orders --file /tmp/orders.ndjson --legacy --drop
# OR: sync to sandbox via koko (skip --legacy, it's handled server-side)
koko import products -s my-api -e sandbox -i /tmp/products.ndjson --upsert
koko import users -s my-api -e sandbox -i /tmp/users.ndjson --upsert
After importing to local, restart your dev server to clear any in-memory caches:
# If using Next.js
rm -rf .next && npm run dev
For development seeds committed to the repo:
# Seeds live in ./seeds/<collection>.ndjson
koko seed -s my-api -e sandbox
# Single collection
koko seed -s my-api -e sandbox --collection products
# Dry-run
koko seed -s my-api -e sandbox --dry-run
koko keys -s my-api -e prod --pattern 'session:*' --limit 100
koko get -s my-api -e prod 'my-api:some-key'
koko redis-info -s my-api -e prod
koko cypher "MATCH (n) RETURN labels(n), count(n) LIMIT 10" -s my-api -e prod
koko neo4j-stats -s my-api -e prod --json
All koko operations are read-only by default:
$out and $merge aggregate stages are blockedCREATE, MERGE, DELETE, SET, REMOVE, DROP are blockedWrite operations (koko import, koko copy, koko seed) require explicit --upsert or --allow-prod confirmation for production targets.
MongoDB stores ObjectIds and Dates as special BSON types (not plain strings). When exported as plain JSON, ObjectId("abc123") becomes the string "abc123" — which looks valid but fails as a MongoDB _id on re-import because the type is wrong.
EJSON preserves the type information:
{ "_id": {"$oid": "abc123..."}, "createdAt": {"$date": "2026-01-15T..."} }
koko export always outputs EJSON. koko import always deserializes it. The round-trip is type-safe by default — no manual conversion scripts needed.
Last updated: July 15, 2026