Deta Space Collections: User-Owned Data Without Running a Database
Deta Space Collections gives each app a per-user key-value store with zero ops, implicit auth, and CLI export/import. This post covers the programming model, local SQLite dev loop, consistency guarantees, and the platform lock-in, size limits, and query gaps you accept when you adopt it.
16 Jul 2026, 01:37 UTC

The Problem: Data Ownership Without Operational Burden
Most side projects and small SaaS products need persistent storage, but running a database—even a managed one—adds cost, configuration, and a persistent operational surface. Deta Space Collections attempts to solve this by giving each Space App an isolated, per-user key-value store that the platform provisions, replicates, and backs up automatically. The developer writes against a simple async map interface; the end user gets data portability via CLI export/import. This post walks through the programming model, the local development loop, and the trade-offs you accept when you adopt it.
Programming Model: Isolated Namespaces, Map-Like API
Every Space App receives a unique Collections namespace keyed by the user's Space ID. Data never mingles across users or apps. The SDK (@deta/space) exposes put, get, delete, and list methods with optional TTL and secondary indexes (string equality only). Writes are durable on acknowledgment and replicated across Deta's regions. Authentication is implicit: the Space runtime injects a short-lived token into the app process, so no API keys or OAuth flows appear in application code.
Consistency is per-key linearizable. Multi-key transactions are not supported, so developers model aggregates as single JSON documents or add a version field for optimistic concurrency. Each item has a 1 MB soft limit; a 10 GB per-app quota applies (soft, raiseable by support ticket). Collections are not a replacement for blob storage or high-throughput time-series workloads.
Local Development: Zero-Config SQLite Backing
During space dev, Collections are backed by an on-disk SQLite file in .space/collections. This enables zero-config iteration and trivial CI testing without a remote dependency. However, the local store does not enforce the 1 MB/item or 10 GB/app quotas, so integration tests must validate limits explicitly. Cold-start latency for the first Collection call in a scaled-to-zero app can exceed 500 ms; warm instances see <10 ms p99.
Worked Example: A Tiny Task List with Export/Import
The following script demonstrates the core loop: create a collection, add tasks, list them, then export and re-import via CLI. Run it inside a Space App directory after npm i @deta/space.
// tasks.js
import { Collection } from '@deta/space';
const tasks = Collection('tasks');
async function demo() {
// Put items with a secondary index on 'status'
await tasks.put({ id: '1', title: 'Write blog', status: 'done', version: 1 });
await tasks.put({ id: '2', title: 'Review PR', status: 'open', version: 1 });
await tasks.put({ id: '3', title: 'Deploy', status: 'open', version: 1 });
// List with index filter
const open = await tasks.list({ status: 'open' });
console.log('Open tasks:', open.items.map(t => t.title));
// Optimistic update
const task = await tasks.get('2');
if (task.version === 1) {
await tasks.put({ ...task, status: 'done', version: 2 });
}
}
demo().catch(console.error);
Run locally:
space dev node tasks.js
Data persists in .space/collections/tasks.sqlite. To export:
space collection export tasks tasks > tasks-backup.jsonlEach line is a JSON document. To restore into a fresh app (or after a migration):
space collection import tasks < tasks-backup.jsonl
This round-trip is scriptable, making user-owned backups a first-class operation.
Trade-offs and Limitations
- Platform lock-in: Collections are tied to the Space runtime. Moving an app elsewhere requires rewriting the persistence layer or running a compatibility shim.
- No transactions or rich queries: No multi-key atomicity, no full-text search, no geospatial indexes. Plan to sync to Typesense or Meilisearch if you need them.
- Size and quota ceilings: 1 MB/item enforced at write time (SDK throws
CollectionItemTooLarge). Large objects must be chunked or stored in Deta Drive with a reference in Collections. Quota increases require a support ticket; no self-serve billing dashboard exists as of the 2024 platform release. - Schema evolution is manual: Deta provides no migration tooling. The JSONL export/import cycle makes manual migrations straightforward but labor-intensive at scale.
When to Use Collections (and When Not To)
Use Collections when you want per-user data isolation without operating a database, when your data model fits single-document aggregates, and when you value user-facing portability (export/import) over query flexibility. Avoid it when you need multi-key transactions, full-text search, time-series ingestion, or the ability to migrate off Space without a persistence rewrite. For a quick validation, create a minimal app (space new), add the SDK, run the script above under space dev, then space push and inspect the Collection in the Horizon UI. Check the Deta Space changelog (docs.deta.space/changelog) for quota or API changes after 2024-06 before committing to production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.