Blog
Designing Apps for Deta Space: Per-User State and the Tenancy Inversion
Deta Space moves app state into each user's own cloud folder, inverting the traditional developer-backed tenancy model. This post walks through the trade-offs, an illustrative notes-app example, and how to verify the isolation yourself.
Published by Tasadduq Burney
28 Jan 2026, 22:02 UTC
4 min32.5K views0

<h2>The Tenancy Inversion Problem</h2><p>Most web applications assume a shared backend: you provision a database, manage a schema that every user hits, and handle migrations as a single operation. Deta Space works differently. In this model, the app code ships to the user’s personal cloud, but the data stays under the user’s own Space key. The developer no longer controls a central database; instead, each installed app instance reads and writes to a collection scoped to that user.</p><h3>Why This Changes the Developer Experience</h3><p>Tenancy inversion means you stop planning for one global data model and start planning per-instance data boundaries. If you need cross-user analytics, you’ll have to build that yourself across many independent stores. If a user deletes their Space, their app data disappears with it—there’s no admin console to recover it from a shared server.</p><h2>Building for Per-User State</h2><h3>The Spacefile and Scoped Collections</h3><p>An app for Deta Space is described declaratively. A manifest file tells the builder what the app is, what data collections it expects, and how it should be packaged. When a user installs the app into their Space, the platform automatically scopes every data operation to that user’s key. Calls that touch collections are routed to the user’s isolated store, and the developer cannot query across installed instances without explicit per-user aggregation.</p><h3>Illustrative Example: A Notes App</h3><pre><code># Spacefile (illustrative only)
name: personal-notes
collections:
- notes
# The platform scopes notes to the installing user's Space key.
# No global table name is required.
// Client code (illustrative only)
import { space } from detasdk
export async function addNote(text) {
// Writes to the user's own notes collection
await space.collections.notes.add({ text, created: now() })
}
export async function listNotes() {
// Reads only from the current user's notes collection
return await space.collections.notes.get()
}
</code></pre><p>The snippets above are illustrative and do not represent verified SDK methods or exact manifest syntax. They aim to convey the idea that collection names are relative to the user's Space, not to a shared backend.</p><h2>Trade-offs and Limitations</h2><ul><li><strong>No cross-user analytics.</strong> To count total notes across all users, you must aggregate per-user queries, which can be costly and rate-limited.</li><li><strong>Per-instance migrations.</strong> If the data schema changes, the migration must run against every user's Space individually. There is no single ALTER TABLE.</li><li><strong>Support blind spots.</strong> When a user reports data loss, the developer may not be able to inspect the records directly, because the data lives in the user's account, not a developer-owned store.</li><li><strong>Product lifecycle uncertainty.</strong> Deta Space's current availability and support status should be verified on the official site before building production-critical dependencies on it.</li></ul><h2>Verifying the Model Yourself</h2><p>If you have a Deta account, the quickest way to confirm the isolation claim is to create a test Space, install a sample Space App from the builder, and navigate to the Space's data section in the Deta UI. You should see the app's collections listed under that user's key, with no records visible from other installed apps. Try adding a record through the app and verify it appears only for that user. This hands-on check costs nothing and gives you concrete confidence before committing to the model.</p><h2>When Per-User Tenancy Makes Sense</h2><p>Per-user data ownership is a reasonable default for small personal tools, diaries, bookmark managers, or anything where the user expects their data to stay under their control. It becomes a poor fit for products whose value comes from aggregate data, network effects, or centralized moderation. In those cases, a shared backend may still be the more practical choice—at least until the tenancy model evolves to support cross-user queries without compromising isolation.</p>
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.