Choosing Between Deta Space's Built-In Base/Drive and an External Database
Deta Space gives every app a free document store (Base) and file storage (Drive). This guide covers when to use them versus an external database, with a concrete Spacefile, SDK example, and verification steps.
13 Sept 2025, 22:09 UTC

When you build a Deta Space app, the platform hands you two data services for free: Deta Base (a schemaless document store) and Deta Drive (file storage). Both are provisioned per app install with zero setup. The real engineering question is not how to use them but whether you should. This guide walks through the decision, then shows a concrete setup and how to verify it works.
Important caveat first: Deta Space's availability has changed over time, and the platform may be deprecated or shut down. Before building anything on it, confirm the service is still operating and that the CLI commands and SDK methods below match the current documentation. Treat everything here as version-sensitive.
The decision in one paragraph
Use built-in Base and Drive when your data is per-user, low-volume, and structurally simple: notes, preferences, session state, small uploads. Choose an external database (reachable over HTTPS) when you need relational queries, joins, aggregations, high throughput, or an exit path for your data. Base supports only simple filters — no joins, no aggregations — and data lives inside the Space app instance, so portability requires an explicit export path.
Decision checklist
| Requirement | Built-in Base/Drive | External database |
|---|---|---|
| Per-user, low-scale data (notes, settings) | Good fit | Overkill |
| Relational queries, joins, aggregations | Not supported | Required |
| Zero ops / no separate account | Yes — auto-provisioned per install | You manage it |
| Data portability / migration path | Manual export needed | Under your control |
| High throughput or large datasets | Not designed for it | Required |
| File/blob storage | Drive handles small files well | Use S3-compatible storage at scale |
Prerequisites
- The Space CLI installed and authenticated (check the current docs for the install command for your OS).
- Node.js or Python locally, matching the runtime you declare.
- A Deta project key for local development. Inside Space, credentials are injected automatically via the
DETA_PROJECT_KEYenvironment variable; locally you must supply it yourself.
Procedure: scaffold, declare, develop, push
Run these from your terminal in an empty project directory. No elevated permissions are needed beyond your authenticated CLI session.
- Scaffold the app:
space new. This creates a starter project and aSpacefile, the YAML manifest that declares your app's runtime and compute units (called Micros). Infrastructure lives in the repo, which is one of Space's genuinely useful ideas. - Define the Spacefile. A minimal Python example:
v: 0
micros:
- name: api
src: ./
engine: python3.9
run: uvicorn main:appField names and supported engines have changed across CLI versions — verify against the docs for your installed CLI (space version).
- Use Base from app code. With the Python SDK, the client auto-detects credentials inside Space:
from deta import Deta
deta = Deta() # reads DETA_PROJECT_KEY automatically
db = deta.Base("notes")
db.put({"text": "hello", "owner": "user-1"}, key="note-1")
item = db.get("note-1")Base items support expiry via expireAt (a timestamp) or expireIn (seconds from write) — handy for sessions or caches, but confirm the exact parameter names in your SDK version.
- Develop locally with
space dev, which emulates the Space runtime. SetDETA_PROJECT_KEYin your shell or a.envfile first, or the SDK will fail to authenticate. - Push your build:
space push. This deploys a revision to your personal Space instance. - When you want to distribute the app via Discovery (Space's app catalog), create a release:
space release. Each user who installs it gets their own isolated Base and Drive — which is the core reason the built-in services fit per-user apps so well.
Verifying the deployment
Do not assume a push worked because the CLI exited cleanly. Check four things:
- App responds: open the assigned Space URL and confirm your app serves its main route.
- Base round-trip: from the deployed app (not locally), put an item, get it back, then delete it. If you use expiry, write an item with a short
expireInand confirm it disappears after the TTL. - Drive round-trip: upload a small file, list the drive, download it, and compare content (a checksum or byte comparison) against the original.
- Logs: inspect logs via the Space CLI or dashboard to catch silent auth or runtime errors.
Limitations and the escape hatch
Two constraints deserve design attention up front. First, Base's query model is shallow: simple equality/range filters only. If you catch yourself denormalizing heavily to work around missing joins, that is the signal to move to an external database. Second, data is tied to the app instance. If portability matters, build a small export endpoint early — iterating Base items and Drive files into JSON/CSV — rather than retrofitting one later. Because the platform's own future is uncertain, having that export path is less optional than it would be on a more established host.
If you outgrow the built-ins, the migration is straightforward in architecture if not in effort: point the same app code at an external database over HTTPS, keep Drive (or an S3-compatible store) for files, and run your export endpoint once to move existing data. No rollback concern applies to the decision itself until you have written production data — before that, switching costs nothing.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.