Skip to content
MonkeyDB

Database power without the learning curve.

Create typed collections, declare indexes once, and query by name instead of rebuilding a storage abstraction around partition keys, GSIs, and tenant safety.

One data plane across SDK, CLI workflows, dashboard views, and MCP-powered agents.

Collection Surface

Declare the collection you want. MonkeyDB handles the storage gymnastics.

const runs = monkey.collection<Run>('runs', {
	indexes: [
		'status',
		{ name: 'byAgentDate', hashKey: 'agentId', rangeKey: 'createdAt' },
	],
})

await runs.query({ index: 'status', hashKey: 'queued' })

Auto-register on first use

Create the collection in code and start writing data immediately. No control plane click-path first.

Query through named indexes

Ask for status or byAgentDate. MonkeyDB handles the backing GSI translation for you.

Use the same data from agents

Collections stay available through the same org auth and MCP surface your app already uses.

Why MonkeyDB

The database layer that feels like product code instead of infrastructure homework.

MonkeyDB keeps the parts that make high-scale storage useful and removes the parts that usually force teams to build their own wrapper first.

Typed from the first call

Use collection<T>() in the SDK, keep your app code honest, and stop inventing one-off wrappers around raw database records.

Indexes by name, not by spelunking

Declare indexes once. MonkeyDB maps them onto shared sparse GSI slots so you query with index names instead of table internals.

Tenant boundaries baked in

Org and namespace isolation sit in the storage model itself, which removes a whole class of cross-tenant query mistakes.

Same data plane for humans and agents

Apps, CLI workflows, and MCP-powered agents hit the same auth, limits, and collection surface instead of parallel tooling stacks.

How It Works

Fast queries without making customers learn GSI archaeology.

The core trick is simple: MonkeyDB exposes named indexes, then maps them onto a fixed pool of sparse shared GSI slots behind the scenes.

1. Declare the shape you want

Create a collection with named indexes like status or byAgentDate. No partition-key design workshop required.

2. MonkeyDB maps the internals

Those named indexes are assigned to one of five shared sparse GSI slots, only when a record actually uses them.

3. Query with the same names

Your app asks for index: "status" and hashKey: "queued". MonkeyDB translates the query to the right GSI path for you.

Index Mapping

Named access patterns in. Shared slots out.

  • All collections share the same five pre-created index slots.
  • Records only pay the write and storage cost for the slots they actually populate.
  • No per-tenant schema updates or table-level migrations when a new collection appears.

runs collection

statusGSI1
byAgentDateGSI2
query
runs.query({ index: 'status', hashKey: 'queued' })

Real Surface Area

The same collection flow in code or on the command line.

These examples match the implemented SDK and CLI surface. No pseudo-API, no marketing-only syntax.

TypeScript SDK

Typed collections, save(), and query() with named indexes.

typescript
import { Monkey } from '@monkeyhub/sdk'

type Run = {
	id: string
	agentId: string
	status: 'queued' | 'running' | 'completed'
	createdAt: string
	prompt: string
}

const monkey = new Monkey(process.env.MONKEY_KEY!)

const runs = monkey.collection<Run>('runs', {
	indexes: [
		'status',
		{ name: 'byAgentDate', hashKey: 'agentId', rangeKey: 'createdAt' },
	],
})

await runs.save({
	id: 'run_001',
	agentId: 'agent_alpha',
	status: 'queued',
	createdAt: '2026-03-16T18:30:00.000Z',
	prompt: 'Summarize incident notes from the night shift',
})

const queued = await runs.query({
	index: 'status',
	hashKey: 'queued',
	limit: 20,
	reverse: true,
})

Monkey CLI

The same collection registration and query flow for scripts and CI jobs.

bash
monkey db save runs \
	--config '{"indexes":["status",{"name":"byAgentDate","hashKey":"agentId","rangeKey":"createdAt"}]}' \
	--input '{"id":"run_001","agentId":"agent_alpha","status":"queued","createdAt":"2026-03-16T18:30:00.000Z","prompt":"Summarize incident notes from the night shift"}'

monkey db query runs \
	--input '{"index":"status","hashKey":"queued","limit":20,"reverse":true}'

Compare

More control than a generic BaaS, less infrastructure work than rolling your own.

MonkeyDB is for teams who want a scalable collection model without turning every new collection into an infrastructure design task.

Need
Roll Your Own
Supabase / Firebase
MonkeyDB
What you manage
Table design, index behavior, key layout, and write amplification.
Schemas, migrations or rules, plus your own tenant model on top.
Collection names and index names. The storage shape stays behind the curtain.
Fast query path
You choose and maintain every access pattern yourself.
Strong general-purpose querying, but not collection-first single-table ergonomics.
Declare the access pattern once, then query through index names.
Multi-tenant isolation
You design the tenant partitioning and hope every caller respects it.
Usually enforced with app logic or RLS/rules you must maintain.
Org plus namespace isolation is built into the record shape.
AI and agent workflows
Build your own SDK conventions and agent tooling surface.
Possible, but usually needs a separate abstraction layer for agents.
The same collections show up through SDK, CLI, dashboard, and MCP.

MonkeyDB on the MonkeyHub data plane

Start with collections. Keep the rest of the stack available when you need it.

Sign up if you want the shortest path to a real org, API keys, and a working collection surface. Or go straight to the quickstart if you want to inspect the implementation details first.