---
title: FAQ
slug: /intro/faq
---

## General

### What is SpacetimeDB?

SpacetimeDB is a database that is also a server. You upload your application logic (called a "module") directly into the database, and clients connect to it without any server in between. It is a relational database with tables, queries, and transactions, but your business logic runs inside it as stored procedures on steroids.

### How is SpacetimeDB different from a traditional backend?

In a traditional stack, you deploy a web server (Node, Django, Rails, etc.) that sits between your clients and your database. You write API endpoints, manage connection pooling, handle caching, and deploy infrastructure.

With SpacetimeDB, you skip all of that. Your module is the backend. Clients connect directly to the database, call reducers (like RPC endpoints), and subscribe to real-time data updates. No separate server, no REST API, no GraphQL layer.

```
Traditional:                    SpacetimeDB:
Client → Server → Database      Client → SpacetimeDB (database + logic)
```

### Is SpacetimeDB only for games?

No. SpacetimeDB is designed for any real-time application: games, chat apps, collaboration tools, dashboards, IoT, or anything that benefits from low-latency state synchronization. Games are a demanding use case that proves SpacetimeDB's performance. Our own MMORPG [BitCraft Online](https://bitcraftonline.com) runs entirely on SpacetimeDB. The same architecture works for any application.

### Is SpacetimeDB open source?

SpacetimeDB is source-available under the [Business Source License 1.1 (BSL)](https://github.com/clockworklabs/SpacetimeDB/blob/master/LICENSE.txt). It converts to the AGPL v3.0 (with a linking exception) after a few years. The linking exception means you are **not** required to open-source your own code if you use SpacetimeDB. You only need to contribute back changes to SpacetimeDB itself.

### Can I self-host SpacetimeDB?

Yes. You can run SpacetimeDB on your own infrastructure using `spacetime start`, or with Docker:

```bash
docker run --rm --pull always -p 3000:3000 clockworklabs/spacetime start
```

You can also use the hosted SpacetimeDB cloud (Maincloud). See the [Deployment & Operations](#deployment--operations) section below for details.

---

## How does SpacetimeDB compare to...

### How is SpacetimeDB different from Mirror / Netcode / Photon / other networking libraries?

Networking libraries like Mirror, Netcode for GameObjects, and Photon handle the transport layer: sending messages between clients and a server you build and deploy yourself. You are still responsible for writing server logic, managing state, handling persistence, and deploying infrastructure.

SpacetimeDB replaces the entire server. Your game state lives in tables, your game logic lives in reducers, and SpacetimeDB automatically synchronizes state to clients in real-time. You do not write networking code, serialization code, or deploy servers.

| | Networking Libraries | SpacetimeDB |
|---|---|---|
| **Server logic** | You write and deploy it | Runs inside the database |
| **State management** | You manage it | Tables with auto-sync |
| **Persistence** | You add a database | Built in |
| **Real-time sync** | You implement it | Automatic via subscriptions |
| **Infrastructure** | You deploy and scale it | Managed or self-hosted |

### How is SpacetimeDB different from Firebase / Supabase?

Firebase and Supabase are Backend-as-a-Service platforms. They give you a database with an API layer on top, but your application logic still runs elsewhere (cloud functions, edge functions, or your own server). Complex business logic is awkward to express as database triggers or serverless functions.

SpacetimeDB lets you write your entire application as a module in a real programming language (Rust, C#, TypeScript) that runs inside the database. You get full transactional guarantees, direct table access, and real-time subscriptions without the cold starts, execution limits, or awkward abstractions of serverless functions.

### How is SpacetimeDB different from a regular database (PostgreSQL, MySQL)?

A traditional database stores data and lets you query it. Your application logic runs in a separate server that connects to the database over the network.

SpacetimeDB holds all data in memory for sub-microsecond access, runs your application logic inside the database as WebAssembly modules, and pushes real-time updates to connected clients automatically. It is purpose-built for real-time applications, not batch processing or analytics. For certain benchmarks, SpacetimeDB can be between 100 and 1000 times faster than a traditional database.

---

## Core Concepts

### What is a "module"?

A module is your application's server-side code compiled to WebAssembly (or bundled as JavaScript for TypeScript modules). It defines your tables, reducers, views, and procedures. You upload it to SpacetimeDB with `spacetime publish`, and it runs inside the database. Think of it as your entire backend in a single deployable unit.

### What are tables?

Tables are the core data storage in SpacetimeDB. You define them in your module using your language's type system. Tables support primary keys, unique constraints, and indexes. Clients can subscribe to tables and receive real-time updates when rows change.

### What are reducers?

Reducers are functions that modify your database state. They run inside a database transaction: either all changes commit or none do. Clients call reducers through auto-generated, type-safe bindings. Think of them as transactional RPC endpoints.

### What are views?

Views are read-only functions that compute derived data from your tables. They are like SQL views but written in your module's language. Clients can subscribe to views just like tables, and they update automatically when the underlying data changes. See [Views](../../00200-core-concepts/00200-functions/00500-views.md) for details.

### What are procedures?

Procedures are similar to reducers but with additional capabilities. They can make HTTP requests to external services and manually manage transactions. Clients can also call procedures over HTTP. Procedures are currently in beta. Use reducers for most cases; use procedures when you need to interact with the outside world. In the future, procedures will be configurable as HTTP endpoints. See [Procedures](../../00200-core-concepts/00200-functions/00400-procedures.md) for details.

---

## Architecture

### How does data persistence work?

SpacetimeDB holds all data in memory for fast access, but persists everything to a commit log (similar to a write-ahead log). On restart, the database replays the commit log to recover its exact state. You get the speed of in-memory computing with the durability of a traditional database.

### How does real-time sync work?

Clients subscribe to typed query builder expressions that specify what data they care about. (Raw SQL subscriptions are also available for advanced use cases.) SpacetimeDB evaluates these subscriptions and pushes incremental updates whenever the underlying data changes. On the client side, the SDK maintains a local cache that mirrors the server state. You query this cache directly with no round trips.

```typescript
// Subscribe to all players
conn.subscriptionBuilder().subscribe(tables.players);

// Subscribe to a filtered subset
conn.subscriptionBuilder().subscribe(
  tables.players.where(p => p.team.eq('red'))
);

// The local cache updates automatically
const players = ctx.db.players;
```

### Are reducers like REST endpoints?

Reducers are more like transactional RPC calls. A client calls a reducer by name with arguments, the reducer runs inside a database transaction, and either all changes commit or none do. Unlike REST, there is no HTTP overhead, no JSON serialization, and no need to design URL routes. Clients call reducers through auto-generated, type-safe bindings.

### What happens if a reducer fails?

The entire transaction rolls back. No partial updates, no corrupted state. The database remains exactly as it was before the reducer was called. You can throw errors or return `Err` freely. SpacetimeDB handles the cleanup.

### What languages can I write modules in?

Server-side modules can be written in:
- **Rust**
- **C#**
- **TypeScript** (new in 2.0)
- **C++** (new in 2.0)

Client SDKs are available for:
- **Rust**
- **C#** (including Unity)
- **TypeScript** (including React, Vue, Svelte, Angular, and more)
- **C++** (Unreal Engine)

SpacetimeDB 2.0 also includes a **type-safe query builder** for client-side subscriptions, so you do not have to write raw SQL strings if you prefer not to.

---

## Development

### How do I get started?

1. Install the CLI: `curl -sSf https://install.spacetimedb.com | sh`
2. Start a local instance: `spacetime start`
3. Create a project: `spacetime init --lang rust` (or `csharp`, `typescript`)
4. Write your module, publish it: `spacetime publish my-app`
5. Generate client bindings: `spacetime generate --lang typescript --out-dir src/module_bindings`
6. Connect from your client using the generated code

See the [quickstart guides](../00200-quickstarts/00100-react.md) for step-by-step tutorials.

### What is `spacetime dev`?

`spacetime dev` is the development workflow command. It watches your module for changes, automatically rebuilds and republishes it, generates client bindings, and optionally starts your client dev server. It is like `npm run dev` but for your entire full-stack application.

### Do I need to write SQL?

No. Your server-side module code uses native language APIs to query and modify tables. For client-side subscriptions, the type-safe query builder is the recommended default. Raw SQL subscriptions are optional for advanced cases.

### Can I use SpacetimeDB with Unity?

Yes. SpacetimeDB has a C# client SDK that works with Unity. The SDK maintains a local cache of your subscribed data and provides callbacks for changes. See the [Unity tutorial](../00300-tutorials/00300-unity-tutorial/index.md) for a complete walkthrough.

### Can I use SpacetimeDB with Unreal Engine?

Yes. SpacetimeDB has a C++ client SDK for Unreal Engine with Blueprint support. See the [Unreal quickstart](../00200-quickstarts/00700-cpp.md) for details.

### Can I use SpacetimeDB with React / Vue / Angular / Svelte?

Yes. The TypeScript SDK includes framework-specific integrations for React, Vue, Angular, Svelte, and more. These provide reactive hooks and composables that automatically update your UI when database state changes.

---

## Authentication & Authorization

### How do I implement auth in my app?

SpacetimeDB uses [OpenID Connect (OIDC)](https://openid.net/developers/how-connect-works/) for authentication. Every reducer call includes the caller's `Identity`, which you can use for authorization logic in your module. You have several options for identity providers:

- **[SpacetimeAuth](../../00200-core-concepts/00500-authentication/00100-spacetimeauth/index.md)**: A fully managed OIDC provider built specifically for SpacetimeDB. The easiest way to get started.
- **Third-party providers**: Any OIDC-compliant provider works, including [Auth0](https://auth0.com/), [Clerk](https://clerk.com/), [Keycloak](https://www.keycloak.org/), Google, GitHub, and others.

See [Authentication](../../00200-core-concepts/00500-authentication.md) for full details.

### Can I use `Identity` as a 1-to-1 mapping with users?

Yes, and this is the recommended approach. Each authenticated user receives a stable `Identity` that persists across sessions. You can store user profiles keyed by `Identity` and use it as your primary user identifier. If you use an OIDC provider (such as SpacetimeAuth, Auth0, or Clerk), the `Identity` is derived from the provider's tokens, so the same user always gets the same `Identity`.

### Can I store passwords in a private table and have users log in by calling a reducer?

This is not recommended. While SpacetimeDB 2.0 no longer exposes reducer arguments to subscribers (the old reducer callback system has been replaced by [Event Tables](../../00200-core-concepts/00300-tables/00550-event-tables.md)), storing and verifying passwords in your module means implementing your own authentication logic, which is error-prone and unnecessary. Use OIDC-based authentication instead, where the identity provider handles credential verification and issues tokens that SpacetimeDB validates.

### How do I create a new localhost identity?

Send a `POST /v1/identity` request to your SpacetimeDB instance. The response includes a new identity and token. See the [HTTP API reference](../../00300-resources/00200-reference/00200-http-api/00200-identity.md#post-v1identity) for details.

:::warning
Identities issued by SpacetimeDB acting as its own identity provider are tied to a single token that does not expire. If that token is lost, there is no way to recover or re-authenticate as that identity. This approach is recommended for **development only**. For production applications, use an external OIDC provider (SpacetimeAuth, Auth0, Clerk, etc.) which provides proper token lifecycle management.
:::

### How do I subscribe to data related to a specific `Identity`?

Build a typed subscription query that filters by the caller identity:

```typescript
conn.subscriptionBuilder().subscribe(
  tables.messages.where(m => m.sender.eq(identity))
);
```

---

## Schema & Migrations

### How do I handle schema migrations?

When you publish an updated module, SpacetimeDB compares the new schema with the existing one and performs automatic migrations for compatible changes (adding tables, adding columns with defaults, etc.). For breaking changes, you may need to publish with `--delete-data` during development. See [Automatic Migrations](../../00200-core-concepts/00100-databases/00500-migrations/00200-automatic-migrations.md) for details on what changes are supported.

### How do I add a column to an existing table?

SpacetimeDB supports adding new columns to the end of a table, provided the new columns have [default values](../../00200-core-concepts/00300-tables/00250-default-values.md). This is handled automatically when you republish your module. For more complex changes (reordering columns, changing types), use the [incremental migration pattern](../../00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md): create a new table with the desired schema and lazily migrate rows from the old table as they are accessed.

### How do I remove a column from an existing table?

Removing columns is not supported through automatic migration. Use [incremental migrations](../../00200-core-concepts/00100-databases/00500-migrations/00300-incremental-migrations.md) instead: create a new table without the column and migrate data incrementally.

### How do I add a new table?

You can simply add the table definition to your module and republish. SpacetimeDB creates new tables automatically during publish.

### How do I add or remove indexes?

You can add or remove indexes by updating the table definition and republishing. Note that removing an index may break client subscription queries that depend on it.

---

## Deployment & Operations

### How do I deploy to production?

You can deploy to [SpacetimeDB Maincloud](https://spacetimedb.com/pricing), our fully managed serverless platform:

```bash
spacetime publish my-app --server maincloud
```

Maincloud handles infrastructure, scaling, replication, and backups. It scales to zero when idle, so you only pay for what you use. There is a free tier with 2,500 TeV of energy credit per month, a Pro tier at $25/month with 100,000 TeV, and Team and Enterprise tiers for larger workloads. See the [pricing page](https://spacetimedb.com/pricing) for full details.

You can also self-host SpacetimeDB and publish to your own server.

### Can I update my module without downtime?

Yes. When you `spacetime publish` an update, SpacetimeDB hot-swaps the module code. Connected clients are not disconnected. They seamlessly continue with the new logic. This is possible because all state lives in tables, not in the server process.

### How do I clear my database?

Use the `-c` (or `--delete-data`) flag when publishing:

```bash
spacetime publish my-app -c
```

This deletes all data and re-runs the `init` reducer.

### Is there a size limit for databases?

SpacetimeDB holds all data in memory, so the practical limit is the available RAM on the host. On Maincloud, resource limits depend on your plan. For self-hosted deployments, you control the hardware.

### How do I build a room-based or match-based game?

SpacetimeDB databases are lightweight and fast to create. The recommended pattern is to use an external orchestration service that creates and destroys SpacetimeDB databases for each room or match. Each database runs an independent instance of your module with its own state.

---

## Troubleshooting

### I'm getting a 401/403 when publishing. What is wrong?

Database names are global on Maincloud. If someone else already published a database with that name, you will get an authorization error. Try a more unique name.

### My `spacetime generate` command gives a confusing error

If your module's `init` reducer panics (for example, due to a unique constraint violation on re-publish), `spacetime generate` may show an unhelpful error like "EOF while parsing a value at line 1 column 0". Fix the runtime error in your module first, then generate again.

### How do I reset my database during development?

Use `spacetime publish my-app --delete-data` to clear all data and republish. Or use `spacetime dev`, which handles this automatically with the `--delete-data=on-conflict` flag.

### I got a weird error when compiling my module!

Make sure you are using the same version of the SpacetimeDB module library (e.g., `spacetimedb` Rust crate, `spacetimedb` npm package, or `SpacetimeDB.ClientSDK` NuGet package) as the version of the SpacetimeDB host you are publishing to. Version mismatches between the module library and the host are a common source of confusing compilation or publish errors.

### I got a weird error when compiling my client!

Make sure the version of the client SDK you are using matches the version of `spacetime generate` that produced your bindings. If you recently updated SpacetimeDB, re-run `spacetime generate` to regenerate your bindings, and update your client SDK to the matching version.
