loading engine version
asmdb is a transactional database engine written from scratch in x86-64 assembly. NASM emits the executable directly — no linker, no C runtime, no libraries. It is fast because it does far less: one fixed-shape row, one hash-indexed table, no parser, no planner.
11,959,261
rows per second, inserted in RAM.
One workstation core, not a hosted tier.
43,749 B
the entire engine, PE64.
52,221 B as ELF64.
0
third-party dependencies.
No linker. No C runtime.
3,145,728
rows in the largest table.
256 bytes each, fixed.
~104 ms
to open a one-million-row
database. 5 MB resident.
The engine
One file holds one table. That same file is simultaneously the unit of durability, of locking, of transactions, of backup and of change capture. There is no catalogue to learn and nothing to configure — which is why it fits in forty kilobytes.
id | u64 — primary key, unique, ≥ 1 O(1) lookup through a hash index |
|---|---|
value | i64 — the numeric column the only column RANGE can filter on |
tag | 39 bytes — one token, no spaces longer input is refused, never truncated |
content | 175 bytes — free text UTF-8 preserved byte for byte |
created · updated | i64 — unix epoch milliseconds set by the engine, not the caller |
$ asmdb notes asmdb> INSERT 1001 5 project asmdb is written in assembly [ OK ] 1 row inserted asmdb> BEGIN [ OK ] transaction started asmdb> UPDATE 1001 9 project revised note [ OK ] 1 row updated asmdb> COMMIT [ OK ] transaction committed asmdb> VERIFY [ OK ] verify: 1 row(s) checked, no problem found
FORMAT TSV switches the same commands to a machine-readable stream.durability
Every transaction goes through a write-ahead log: the changes are staged and
flushed, a commit marker and its CRC-32 are flushed, a change frame is
appended and flushed, and only then is the data file touched. A crash
resumes from the log. Whole-table operations are announced in the header
before they start, so an interrupted TRUNCATE finishes on the
next open instead of leaving half a table.
capture
Each committed transaction appends one frame to an append-only change log —
a total order, a dense sequence, and enough identity to refuse a log that
belongs to a different database. Anything downstream can follow the database
exactly, and CDCTRIM reclaims what has been acknowledged.
concurrency
Reader sessions take no lock at all and run beside the writer. Each command is bracketed by the commit sequence, so a reader never observes a half-applied transaction. Writes do not scale within one instance — that is a real limit, and it is the reason the unit of scale here is the instance.
honesty
No SQL, no joins, no query planner, no secondary indexes — a FIND
scans the whole slot region. No authentication, no encryption and no audit log
inside the engine; that is the platform's job, and it is written down rather
than implied.
Model Context Protocol
Every instance speaks MCP over HTTP with the same tools as the local stdio server. Point a Model Context Protocol client at the endpoint and an agent has durable, transactional memory — with real timestamps, real transactions and a change log, instead of a vector blob it cannot audit.
db_insert
store a row by key or numeric id
db_get
read one row, whole and untruncated
db_update
overwrite, bumping updated
db_delete
remove one row by key
db_find
substring search, paginated
db_list
page through every row
db_count
how many rows are live
Identifiers and values cross the wire as decimal strings — a u64 key and an i64 value do not survive a JavaScript number, and silently rounding someone's primary key is not a trade-off worth making.
// claude_desktop_config.json — or any MCP client { "mcpServers": { "asmdb": { "url": "https://<gateway-host>/db/7k2m9x4qp1va8ne03wjr5tzy/mcp", "headers": { "Authorization": "Bearer <your token>" } } } }
# or run it locally against a file, no cloud at all npx asmdb-mcp --db ./memory
Web applications
The instance access token is a bearer token with full authority over that
database: read, write, delete and TRUNCATE. A web application
calls asmdb from its server. The browser talks to your backend, never to
the database directly, and the private database environment is not
reachable from the public internet.
// app/api/notes/route.ts — server-side only const endpoint = process.env.ASMDB_ENDPOINT!; // returned as https://<gateway-host>/db/7k2m9x4qp1va8ne03wjr5tzy const token = process.env.ASMDB_INSTANCE_TOKEN!; type Row = { id: string; value: string; tag: string; content: string; created: string; updated: string }; async function asmdb(path: string, init: RequestInit = {}) { return fetch(`${endpoint}${path}`, { ...init, headers: { authorization: ["Bearer", token].join(" "), "content-type": "application/json", ...init.headers } }); } export async function GET() { const res = await asmdb("/v1/rows?limit=100&offset=0"); const data = await res.json() as { rows: Row[]; count: number; hasMore: boolean; nextOffset: number }; return Response.json(data); } export async function POST(request: Request) { const body = await request.json() as { id: string; value: string; tag: string; content: string }; const res = await asmdb("/v1/rows", { method: "POST", body: JSON.stringify(body) }); return Response.json(await res.json() as { row: Row }, { status: res.status }); }
strings
Numeric fields cross the wire as decimal strings. id is
u64 and value is i64; neither should be parsed as a
JavaScript number.
limits
tag is 39 bytes and content is 175 bytes.
Longer input is refused, not truncated, so forms should validate
before posting.
paging
Listings default to limit=100, cap at 1000
and page with offset. FIND and
RANGE are full scans, not keystroke-by-keystroke search
endpoints.
shape
One database is one fixed-shape table. There is no
CREATE TABLE, no joins and no schema migration step.
Backends do not have to be JavaScript. Python, C# and C clients ship in
the repository under clients/.
Three ways in
# REST — every field is a string, on purpose curl -X POST https://<gateway-host>/db/7k2m9x4qp1va8ne03wjr5tzy/v1/rows \ -H "Authorization: Bearer $TOKEN" \ -d '{"id":"1001","value":"5", "tag":"project","content":"hello"}' curl https://<gateway-host>/db/7k2m9x4qp1va8ne03wjr5tzy/v1/rows?limit=100 \ -H "Authorization: Bearer $TOKEN"
limit caps at 1000.# Python — the client speaks the engine's own protocol from asmdb import Client db = Client(url, token) db.insert("1001", value="5", tag="project", content="asmdb in assembly") for row in db.find("assembly", limit=50): print(row.id, row.content)
Tiers
Tiers buy latency and headroom — never features. Durability guarantees and the change log are identical on every tier, because they are properties of the engine, not of a price list; the row ceiling follows the memory each tier is given. The last two are on the roadmap and cannot be bought yet. Prices are USD per month; the cost basis is published in the repository.
Free
$0USD / month
Standard
$15USD / month
Premium
$49USD / month
Premium+ not yet built
$89USD / month
Enterprise not yet built
Contact usannual contract + usage
Free uses 0.25 vCPU / 0.5 GiB because Container Apps Consumption has no smaller 1:2 CPU-to-memory pair. The row ceiling follows the memory: the engine's slot table is resident memory, not a file mapping, so each tier gets the largest table its memory can hold. Premium keeps a replica resident; the price buys no cold start, not a different engine.
What the throughput figure above is not: it is one workstation core with
the data in RAM. A hosted tier gives you a fraction of a core — a quarter
on free, a half on standard, one on premium — so expect throughput in that
proportion, less the REST and gateway hops. The engine is identical; the
machine is not. Tiers that sleep also pay a cold start on the first request
after idling. Every number on this page is measured, and the one that
matters for your workload is the one you measure yourself: the CLI ships a
BENCH command that writes real rows into your own database.
The engine remains identical on every tier; these are service capabilities planned for GA.
| Capability | Free | Standard | Premium |
|---|---|---|---|
| Microsoft Fabric Workload | ✗ | ✗ | ✓ |
| Automated backups | ✗ | ✓ | ✓ |
Binaries
The Windows and Linux binaries are assembled from the same source tree with
nasm -f bin. There is no linker and no C runtime; the PE64 build is
emitted on Linux by writing different bytes, not by cross-compiling through a toolchain.
Standalone executable files. Nothing to install, no dependencies.
Linux downloads need chmod +x before running.
Security posture is documented in SECURITY.md, including the single RWX image at a fixed address.
Provision
Creation, access, monitoring and CLI commands are separated so the selected database is always explicit. The instance token is shown once at creation; this tab can hold it for the session, or you can rotate it if it is lost.
Console access
Provisioning and the browser CLI are restricted to members of the ASMDB_ADMIN security group. There are no local users, passwords or public sign-up path.
Not signed in.
The public site remains available. Sign in to create databases and open the CLI.
Create
Access
Choose the instance you intend to inspect. Management calls use your Entra token.
Token
Paste the selected database token to preview rows or run CLI commands. It is not an Entra token.
masked
Rotate token if the original was lost. Rotation issues a new token, invalidates the old one immediately, restarts the instance, and interrupts existing clients until they are updated.
Database view
Open a database from Access before previewing data.
Preview
Reads /v1/rows?limit=5&offset=0. The table scrolls inside this frame on narrow screens.
| id | value | tag | content | updated |
|---|---|---|---|---|
| Select a database. | ||||
Monitoring
rows
No sample yet
Rows are shown against capacity when the instance is running.
cpu
—
derived from two samples; first sample is not displayed as zero
memory
No sample yet
working set, not reclaimable page cache
allocated storage —
CLI
Bench
This writes real rows into the selected database.
Costs
Paused hours are shown explicitly because free and standard databases can scale to zero. See the cost model.
| Database | Tier | Size | State | Active hours | Paused hours | Estimated cost |
|---|---|---|---|---|---|---|
| Open the cost view to load estimates. | ||||||