Skip to content
Docs · Data

Databases

Edge SQLite databases queried over HTTPS with an API key: single statements, batches of up to 100, and .sql export. Each database is its own SQLite database of up to 10 GB, inside the database storage your plan includes (0.5 GB in all on Hobby).

View as Markdown
All topics
On this page

Every database you create is a separate SQLite database on the edge — two databases never share a file or a table. Engine "sqlite" is the one available today; Postgres, MySQL and Redis answer 501 until they exist.

There is no host and port: every query is a POST https://harakumo.com/api/databases/:id with an API key. Keep the key on your server.

SELECT * FROM users;idemailstatus1ada@example.comactive2grace@example.comactive3linus@example.cominvitedPOST /api/databases/:idEdge SQLiteplain SQL over HTTP — no drivers, no connection pools

Connect from your app

  1. Create the database (dashboard, CLI or POST /api/projects/:id/databases { name }) and note its id. The database page's Connect tab shows the endpoint, the id and snippets with your real values.
  2. Create an API key limited to the project (Settings → API access; full access, Project set). Queries need full access, even for SELECT.
  3. Put the key and the database id in the project's environment variables (for example HARAKUMO_API_KEY and NOTES_DB_ID) and redeploy.
  4. Query from server code: the SDK, fetch or curl.
fetch
const res = await fetch('https://harakumo.com/api/databases/' + process.env.NOTES_DB_ID, {
  method: 'POST',
  headers: { authorization: 'Bearer ' + process.env.HARAKUMO_API_KEY, 'content-type': 'application/json' },
  body: JSON.stringify({ sql: 'SELECT * FROM notes WHERE id = ?', params: [42] }),
});
const { results, meta } = await res.json();   // results: rows of the last statement
curl
curl -X POST https://harakumo.com/api/databases/5 \
  -H "Authorization: Bearer $HARAKUMO_API_KEY" -H "content-type: application/json" \
  -d '{ "sql": "SELECT count(*) AS n FROM notes" }'

Responses

  • A single request answers { results, statements, meta }. SQL holding several statements runs them in order; results holds the last statement's rows and statements how many ran.
  • meta has the rows read and written, changes and last_row_id from the database.
  • Use ? placeholders with params for every value — never build SQL by joining strings.

Batch

Send up to 100 statements, each with its own params, in one request. It counts once toward the workspace rate limit, so batching is the way to do bulk work. Do not rely on a failing statement rolling back the earlier ones in the same batch until that behavior is confirmed; design writes to be safe to retry.

Batch
curl -X POST https://harakumo.com/api/databases/5 \
  -H "Authorization: Bearer $HARAKUMO_API_KEY" -H "content-type: application/json" \
  -d '{ "batch": [
        { "sql": "INSERT INTO notes (body) VALUES (?)", "params": ["first"] },
        { "sql": "INSERT INTO notes (body) VALUES (?)", "params": ["second"] },
        { "sql": "SELECT count(*) AS n FROM notes" } ] }'
# → { "batch": [ { "results": [], "meta": {…} }, …, { "results": [{ "n": 2 }], "meta": {…} } ] }

Export

POST /api/databases/:id/export starts an export and answers { status: "active", bookmark } while it runs; call again with the bookmark until it answers { status: "complete", download }. GET /api/databases/:id/export?bookmark=… returns the .sql file (schema and data), which any SQLite tool can load. The Connect tab has an Export button.

There is no point-in-time restore or import through Harakumo yet. Export regularly if the data matters, and treat delete as permanent.

Limits

LimitValue
Size of one database10 GB
One row or value2 MB
One SQL statement100 KB
Bound parameters per statement100
Time per query30 seconds
Columns per table100
Statements per batch100
Query requests per workspace600 per 5 minutes
Databases per plan1 hobby, 10 pro, 100 enterprise
Database storage per plan (all databases together)0.5 GB hobby, 10 GB pro, 100 GB enterprise, measured daily; on Hobby, across all your free workspaces

On Hobby, database writes that add data (reads and deletes still work) are refused once the plan's database storage allowance is used up (402 usage_limit). On Pro and Enterprise, use past it is charged daily from the Balance at $1.00 per GB a month, and database writes that add data pause (402 usage_paused) only while a charge cannot be paid.

Errors

StatusMeaning
400A SQL mistake; the message is the database's own.
402The plan's database storage is used up, so statements that add data (INSERT, UPDATE, REPLACE, UPSERT, CREATE, ALTER) are held: usage_limit on Hobby, usage_paused on a paid plan that cannot pay for more. Reads, DELETE and DROP still run, so you can clean up (a DELETE is held too when the database has triggers, since a trigger can add data when rows are deleted: drop the triggers first), but a batch that contains any statement that adds data is held as a whole: send reads and deletes in a batch of their own. A word inside quotes, a quoted name or a comment does not count. The size is measured again daily, so room you free counts from the next measurement.
409The database is not available (its create failed, or it was never created). A failed create shows the reason; retry with PATCH { "action": "retry" } — it does not count against the plan.
410The database no longer exists on the edge.
429The workspace rate limit or the database service is throttling. Wait Retry-After seconds, and batch.
502 / 503A platform problem. Retry shortly.

How it scales

Each database has one writer and stops at 10 GB, and every query is an HTTPS call through Harakumo, capped at 600 requests per 5 minutes per workspace. That suits development, internal tools and low-traffic apps. For more: batch statements, cache reads in your app, and split data across several databases (per customer, per region). Direct connections from your functions and apps, read replicas and a Postgres engine for single datasets over 10 GB are planned.

Moving from MongoDB

@harakumo/docdb keeps the MongoDB and Mongoose call shapes (find, updateOne, populate, bulkWrite …) and stores documents as JSON in a Harakumo database, so an app moves without rewriting every query. It is in preview and not yet published to npm; ask support for access.

Reference

SDK
const { database } = await hk.databases.create(project.id, { name: 'app', engine: 'sqlite' });
const { results } = await hk.databases.query(database.id, 'SELECT * FROM users WHERE id = ?', [42]);
// Batches and export are REST calls (below); the SDK sends single statements.