Files
SpacetimeDB/docs/build/index.html
T
Julien Lavocat c20c30524b Remove old docs
2025-10-21 12:12:01 +02:00

213 lines
52 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-Intro/overview" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.9.1">
<title data-rh="true">Overview | SpacetimeDB docs</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://docs.spacetimedb.com/"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Overview | SpacetimeDB docs"><meta data-rh="true" name="description" content="Installation"><meta data-rh="true" property="og:description" content="Installation"><link data-rh="true" rel="icon" href="/images/favicon.ico"><link data-rh="true" rel="canonical" href="https://docs.spacetimedb.com/"><link data-rh="true" rel="alternate" href="https://docs.spacetimedb.com/" hreflang="en"><link data-rh="true" rel="alternate" href="https://docs.spacetimedb.com/" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://QBC7Z9KXS2-dsn.algolia.net" crossorigin="anonymous"><script data-rh="true">function insertBanner(){var n=document.createElement("div");n.id="__docusaurus-base-url-issue-banner-container";n.innerHTML='\n<div id="__docusaurus-base-url-issue-banner" style="border: thick solid red; background-color: rgb(255, 230, 179); margin: 20px; padding: 20px; font-size: 20px;">\n <p style="font-weight: bold; font-size: 30px;">Your Docusaurus site did not load properly.</p>\n <p>A very common reason is a wrong site <a href="https://docusaurus.io/docs/docusaurus.config.js/#baseUrl" style="font-weight: bold;">baseUrl configuration</a>.</p>\n <p>Current configured baseUrl = <span style="font-weight: bold; color: red;">/</span> (default value)</p>\n <p>We suggest trying baseUrl = <span id="__docusaurus-base-url-issue-banner-suggestion-container" style="font-weight: bold; color: green;"></span></p>\n</div>\n',document.body.prepend(n);var e=document.getElementById("__docusaurus-base-url-issue-banner-suggestion-container"),s=window.location.pathname,o="/"===s.substr(-1)?s:s+"/";e.innerHTML=o}document.addEventListener("DOMContentLoaded",function(){void 0===window.docusaurus&&insertBanner()})</script><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Overview","item":"https://docs.spacetimedb.com/"}]}</script><link rel="search" type="application/opensearchdescription+xml" title="SpacetimeDB docs" href="/opensearch.xml"><link rel="stylesheet" href="/assets/css/styles.0cb9f7a7.css">
<script src="/assets/js/runtime~main.d71df0f5.js" defer="defer"></script>
<script src="/assets/js/main.31d95d83.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>document.documentElement.setAttribute("data-theme","light"),document.documentElement.setAttribute("data-theme-choice","light"),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="https://spacetimedb.com/images/brand.png"><link rel="preload" as="image" href="/images/basic-architecture-diagram.png"><link rel="preload" as="image" href="/images/workflow-preview-diagram.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_6jFv" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="https://spacetimedb.com/images/brand.png" alt="SpacetimeDB Logo" class="themedComponent_rvet themedComponent--light_mbAJ"><img src="https://spacetimedb.com/images/brand.png" alt="SpacetimeDB Logo" class="themedComponent_rvet themedComponent--dark_Ncy6"></div></a><div class="navbarSearchContainer_AesG"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search (Command+K)"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://spacetimedb.com/install" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Install</a><a href="https://spacetimedb.com/pricing" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Pricing</a><a href="https://spacetimedb.com/maincloud" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Maincloud</a><a href="https://spacetimedb.com/blog" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Blog</a><a href="https://spacetimedb.com/community" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">Community</a></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_hV_y"><div class="docsWrapper_f07g"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_MJiz" type="button"></button><div class="docRoot_Gd2s"><aside class="theme-doc-sidebar-container docSidebarContainer_fSpF"><div class="sidebarViewport_YElg"><div class="sidebar_kjg4"><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_AG0n"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role="button" aria-expanded="true" href="/"><span title="Intro" class="categoryLinkLabel_EDYQ">Intro</span></a></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/"><span title="Overview" class="linkLabel_dpMB">Overview</span></a></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/getting-started"><span title="Getting Started" class="linkLabel_dpMB">Getting Started</span></a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/deploying/maincloud"><span title="Deploying" class="categoryLinkLabel_EDYQ">Deploying</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/unity"><span title="Unity tutorial" class="categoryLinkLabel_EDYQ">Unity tutorial</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/unreal"><span title="Unreal Tutorial" class="categoryLinkLabel_EDYQ">Unreal Tutorial</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/cli-reference"><span title="CLI Reference" class="categoryLinkLabel_EDYQ">CLI Reference</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/modules"><span title="Server Module Languages" class="categoryLinkLabel_EDYQ">Server Module Languages</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/sdks"><span title="Client SDK Languages" class="categoryLinkLabel_EDYQ">Client SDK Languages</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/sql"><span title="SQL" class="categoryLinkLabel_EDYQ">SQL</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/subscriptions"><span title="Subscriptions" class="categoryLinkLabel_EDYQ">Subscriptions</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/rls"><span title="Row Level Security" class="linkLabel_dpMB">Row Level Security</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/how-to/incremental-migrations"><span title="How-To" class="categoryLinkLabel_EDYQ">How-To</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/spacetimeauth"><span title="SpacetimeAuth" class="categoryLinkLabel_EDYQ">SpacetimeAuth</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/http/authorization"><span title="HTTP API" class="categoryLinkLabel_EDYQ">HTTP API</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_ggI5 menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/webassembly-abi"><span title="Internals" class="categoryLinkLabel_EDYQ">Internals</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 menu__list-item"><a class="menu__link" href="/appendix"><span title="Appendix" class="linkLabel_dpMB">Appendix</span></a></li></ul></nav></div></div></aside><main class="docMainContainer_dkUT"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_w2oE"><div class="docItemContainer_f71m"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_xsLZ" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_oyay"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><span class="breadcrumbs__link">Intro</span></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">Overview</span></li></ul></nav><div class="tocCollapsible_dqme theme-doc-toc-mobile tocMobile_Z34P"><button type="button" class="clean-btn tocCollapsibleButton_QMSE">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>SpacetimeDB Documentation</h1></header>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="installation">Installation<a href="#installation" class="hash-link" aria-label="Direct link to Installation" title="Direct link to Installation" translate="no"></a></h2>
<p>You can run SpacetimeDB as a standalone database server via the <code>spacetime</code> CLI tool.</p>
<p>You can find the instructions to install the CLI tool for your platform <a href="https://spacetimedb.com/install" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>To get started running your own standalone instance of SpacetimeDB check out our <a href="/getting-started">Getting Started Guide</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="what-is-spacetimedb">What is SpacetimeDB?<a href="#what-is-spacetimedb" class="hash-link" aria-label="Direct link to What is SpacetimeDB?" title="Direct link to What is SpacetimeDB?" translate="no"></a></h2>
<p>SpacetimeDB is a database that is also a server.</p>
<p>SpacetimeDB is a full-featured relational database system that lets you run your application logic <strong>inside</strong> the database. You no longer need to deploy a separate web or game server. <a href="#module-libraries">Several programming languages</a> are supported, including C# and Rust. You can still write authorization logic, just like you would in a traditional server.</p>
<p>This means that you can write your entire application in a single language and deploy it as a single binary. No more microservices, no more containers, no more Kubernetes, no more Docker, no more VMs, no more DevOps, no more infrastructure, no more ops, no more servers.</p>
<figure><img src="/images/basic-architecture-diagram.png" alt="SpacetimeDB Architecture" style="width:100%"><figcaption style="margin-top:10px;text-align:center" align="center"><b align="center">SpacetimeDB application architecture</b><span style="font-size:14px"> <p>(elements in white are provided by SpacetimeDB)</p></span></figcaption></figure>
<p>This is similar to <a href="https://en.wikipedia.org/wiki/Smart_contract" target="_blank" rel="noopener noreferrer">&quot;smart contracts&quot;</a>, except that SpacetimeDB is a <strong>database</strong> and has nothing to do with blockchain. Because it isn&#x27;t a blockchain, it can be dramatically faster than many &quot;smart contract&quot; systems.</p>
<p>In fact, it&#x27;s so fast that we&#x27;ve been able to write the entire backend of our MMORPG <a href="https://bitcraftonline.com" target="_blank" rel="noopener noreferrer">BitCraft Online</a> as a single SpacetimeDB database. Everything in the game -- chat messages, items, resources, terrain, and player locations -- is stored and processed by the database. SpacetimeDB <a href="#state-mirroring">automatically mirrors</a> relevant state to connected players in real-time.</p>
<p>SpacetimeDB is optimized for maximum speed and minimum latency, rather than batch processing or analytical workloads. It is designed for real-time applications like games, chat, and collaboration tools.</p>
<p>Speed and latency is achieved by holding all of your application state in memory, while persisting data to a commit log which is used to recover data after restarts and system crashes.</p>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="application-workflow-preview">Application Workflow Preview<a href="#application-workflow-preview" class="hash-link" aria-label="Direct link to Application Workflow Preview" title="Direct link to Application Workflow Preview" translate="no"></a></h2>
<figure><img src="/images/workflow-preview-diagram.png" alt="SpacetimeDB Application Workflow Preview" style="width:100%"><figcaption style="margin-top:10px;text-align:center" align="center"><b align="center">SpacetimeDB Application Workflow Preview</b></figcaption></figure>
<p>The above illustrates the workflow when using SpacetimeDB.</p>
<ul>
<li>
<p>All client-side reads happen with the data view that is cached locally.</p>
</li>
<li>
<p>Client-side subscriptions tell the server what data client cares about and wants to be synced within its data view. Changes to data will be pushed by the server to the client cache.</p>
</li>
<li>
<p>RLS filters restrict the data view server-side before subscriptions are evaluated. These filters can be used for access control or client scoping.</p>
</li>
<li>
<p>Reducers are effectively async RPC&#x27;s. The request is sent off and if the results of that reducer makes changes to data, it will be written to the database directly. As a result of that, if those changes make it through the two layers above, then the client will see the result when it queries its local cache.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="state-mirroring">State Mirroring<a href="#state-mirroring" class="hash-link" aria-label="Direct link to State Mirroring" title="Direct link to State Mirroring" translate="no"></a></h2>
<p>SpacetimeDB can generate client code in a <a href="#client-side-sdks">variety of languages</a>. This creates a client library custom-designed to talk to your database. It provides easy-to-use interfaces for connecting to the database and submitting requests. It can also <strong>automatically mirror state</strong> from your database to client applications.</p>
<p>You write SQL queries specifying what information a client is interested in -- for instance, the terrain and items near a player&#x27;s avatar. SpacetimeDB will generate types in your client language for the relevant tables, and feed clients a stream of live updates whenever the database state changes. Note that this is a <strong>read-only</strong> mirror -- the only way to change the database is to submit requests, which are validated on the server.</p>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="language-support">Language Support<a href="#language-support" class="hash-link" aria-label="Direct link to Language Support" title="Direct link to Language Support" translate="no"></a></h2>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="module-libraries">Module Libraries<a href="#module-libraries" class="hash-link" aria-label="Direct link to Module Libraries" title="Direct link to Module Libraries" translate="no"></a></h3>
<p>Every SpacetimeDB database contains a collection of <a href="https://en.wikipedia.org/wiki/Stored_procedure" target="_blank" rel="noopener noreferrer">stored procedures</a> and schema definitions. Such a collection is called a <strong>module</strong>, which can be written in C# or Rust. They specify a database schema and the business logic that responds to client requests. Modules are administered using the <code>spacetime</code> CLI tool.</p>
<ul>
<li><a href="/modules/rust">Rust</a> - <a href="/modules/rust/quickstart">(Quickstart)</a></li>
<li><a href="/modules/c-sharp">C#</a> - <a href="/modules/c-sharp/quickstart">(Quickstart)</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="client-side-sdks">Client-side SDKs<a href="#client-side-sdks" class="hash-link" aria-label="Direct link to Client-side SDKs" title="Direct link to Client-side SDKs" translate="no"></a></h3>
<p><strong>Clients</strong> are applications that connect to SpacetimeDB databases. The <code>spacetime</code> CLI tool supports automatically generating interface code that makes it easy to interact with a particular database.</p>
<ul>
<li><a href="/sdks/rust">Rust</a> - <a href="/sdks/rust/quickstart">(Quickstart)</a></li>
<li><a href="/sdks/c-sharp">C#</a> - <a href="/sdks/c-sharp/quickstart">(Quickstart)</a></li>
<li><a href="/sdks/typescript">TypeScript</a> - <a href="/sdks/typescript/quickstart">(Quickstart)</a></li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="unity">Unity<a href="#unity" class="hash-link" aria-label="Direct link to Unity" title="Direct link to Unity" translate="no"></a></h3>
<p>SpacetimeDB was designed first and foremost as the backend for multiplayer Unity games. To learn more about using SpacetimeDB with Unity, jump on over to the <a href="/unity/part-1">SpacetimeDB Unity Tutorial</a>.</p>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="key-architectural-concepts">Key architectural concepts<a href="#key-architectural-concepts" class="hash-link" aria-label="Direct link to Key architectural concepts" title="Direct link to Key architectural concepts" translate="no"></a></h2>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="host">Host<a href="#host" class="hash-link" aria-label="Direct link to Host" title="Direct link to Host" translate="no"></a></h3>
<p>A SpacetimeDB <strong>host</strong> is a server that hosts <a href="#database">databases</a>. You can run your own host, or use the SpacetimeDB maincloud. Many databases can run on a single host.</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="database">Database<a href="#database" class="hash-link" aria-label="Direct link to Database" title="Direct link to Database" translate="no"></a></h3>
<p>A SpacetimeDB <strong>database</strong> is an application that runs on a <a href="#host">host</a>.</p>
<p>A database exports <a href="#table">tables</a>, which store data, and <a href="#reducer">reducers</a>, which allow <a href="#client">clients</a> to make requests.</p>
<p>A database&#x27;s schema and business logic is specified by a piece of software called a <strong>module</strong>. Modules can be written in C# or Rust.</p>
<p>(Technically, a SpacetimeDB module is a <a href="https://developer.mozilla.org/en-US/docs/WebAssembly" target="_blank" rel="noopener noreferrer">WebAssembly module</a> that imports a specific low-level <a href="/webassembly-abi">WebAssembly ABI</a> and exports a small number of special functions. However, the SpacetimeDB <a href="#module-libraries">server-side libraries</a> hide these low-level details. As a developer, writing a module is mostly like writing any other C# or Rust application, except for the fact that a <a href="https://spacetimedb.com/install" target="_blank" rel="noopener noreferrer">special CLI tool</a> is used to deploy the application.)</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="table">Table<a href="#table" class="hash-link" aria-label="Direct link to Table" title="Direct link to Table" translate="no"></a></h3>
<p>A SpacetimeDB <strong>table</strong> is a SQL database table. Tables are declared in a module&#x27;s native language. For instance, in C#, a table is declared like so:</p>
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">#[spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#F8F8F2">table(name </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> players, public)]</span></span>
<span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> struct</span><span style="color:#8BE9FD;font-style:italic"> Player</span><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#F8F8F2"> #[primary_key]</span></span>
<span class="line"><span style="color:#F8F8F2"> id</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> u64</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2"> name</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> String</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2"> age</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> u32</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2"> user</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> Identity</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">[</span><span style="color:#8BE9FD;font-style:italic">SpacetimeDB</span><span style="color:#F8F8F2">.</span><span style="color:#8BE9FD;font-style:italic">Table</span><span style="color:#F8F8F2">(Name </span><span style="color:#FF79C6">=</span><span style="color:#E9F284"> &quot;</span><span style="color:#F1FA8C">players</span><span style="color:#E9F284">&quot;</span><span style="color:#F8F8F2">, Public </span><span style="color:#FF79C6">=</span><span style="color:#BD93F9"> true</span><span style="color:#F8F8F2">)]</span></span>
<span class="line"><span style="color:#FF79C6">public</span><span style="color:#FF79C6"> partial</span><span style="color:#FF79C6"> struct</span><span style="color:#8BE9FD;font-style:italic"> Player</span></span>
<span class="line"><span style="color:#F8F8F2">{</span></span>
<span class="line"><span style="color:#F8F8F2"> [</span><span style="color:#8BE9FD;font-style:italic">SpacetimeDB</span><span style="color:#F8F8F2">.</span><span style="color:#8BE9FD;font-style:italic">PrimaryKey</span><span style="color:#F8F8F2">]</span></span>
<span class="line"><span style="color:#FF79C6"> uint</span><span style="color:#F8F8F2"> playerId;</span></span>
<span class="line"><span style="color:#FF79C6"> string</span><span style="color:#F8F8F2"> name;</span></span>
<span class="line"><span style="color:#FF79C6"> uint</span><span style="color:#F8F8F2"> age;</span></span>
<span class="line"><span style="color:#8BE9FD;font-style:italic"> Identity</span><span style="color:#F8F8F2"> user;</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div></div></div>
<p>The contents of a table can be read and updated by <a href="#reducer">reducers</a>.
Tables marked <code>public</code> can also be read by <a href="#client">clients</a>.</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="reducer">Reducer<a href="#reducer" class="hash-link" aria-label="Direct link to Reducer" title="Direct link to Reducer" translate="no"></a></h3>
<p>A <strong>reducer</strong> is a function exported by a <a href="#database">database</a>.
Connected <a href="#client-side-sdks">clients</a> can call reducers to interact with the database.
This is a form of <a href="https://en.wikipedia.org/wiki/Remote_procedure_call" target="_blank" rel="noopener noreferrer">remote procedure call</a>.</p>
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><p>A reducer can be written in Rust like so:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">#[spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#F8F8F2">reducer]</span></span>
<span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> set_player_name</span><span style="color:#F8F8F2">(ctx</span><span style="color:#FF79C6">:</span><span style="color:#FF79C6"> &amp;</span><span style="color:#F8F8F2">spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#F8F8F2">, id</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> u64</span><span style="color:#F8F8F2">, name</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> String</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-&gt;</span><span style="color:#8BE9FD;font-style:italic"> Result</span><span style="color:#F8F8F2">&lt;(), </span><span style="color:#8BE9FD;font-style:italic">String</span><span style="color:#F8F8F2">&gt; {</span></span>
<span class="line"><span style="color:#6272A4"> // ...</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre><p>And a Rust <a href="#client">client</a> can call that reducer:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">fn</span><span style="color:#50FA7B"> main</span><span style="color:#F8F8F2">() {</span></span>
<span class="line"><span style="color:#6272A4"> // ...setup code, then...</span></span>
<span class="line"><span style="color:#F8F8F2"> ctx</span><span style="color:#FF79C6">.</span><span style="color:#F8F8F2">reducers</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">set_player_name</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9">57</span><span style="color:#F8F8F2">, </span><span style="color:#F1FA8C">&quot;Marceline&quot;</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">into</span><span style="color:#F8F8F2">());</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div><div role="tabpanel" class="tabItem_sydm" hidden=""><p>A reducer can be written in C# like so:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">[</span><span style="color:#8BE9FD;font-style:italic">SpacetimeDB</span><span style="color:#F8F8F2">.</span><span style="color:#8BE9FD;font-style:italic">Reducer</span><span style="color:#F8F8F2">]</span></span>
<span class="line"><span style="color:#FF79C6">public</span><span style="color:#FF79C6"> static</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> SetPlayerName</span><span style="color:#F8F8F2">(</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#FFB86C;font-style:italic"> ctx</span><span style="color:#F8F8F2">, </span><span style="color:#FF79C6">uint</span><span style="color:#FFB86C;font-style:italic"> playerId</span><span style="color:#F8F8F2">, </span><span style="color:#FF79C6">string</span><span style="color:#FFB86C;font-style:italic"> name</span><span style="color:#F8F8F2">)</span></span>
<span class="line"><span style="color:#F8F8F2">{</span></span>
<span class="line"><span style="color:#6272A4"> // ...</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre><p>And a C# <a href="#client">client</a> can call that reducer:</p><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">void</span><span style="color:#50FA7B"> Main</span><span style="color:#F8F8F2">() {</span></span>
<span class="line"><span style="color:#6272A4"> // ...setup code, then...</span></span>
<span class="line"><span style="color:#F8F8F2"> Connection.Reducer.</span><span style="color:#50FA7B">SetPlayerName</span><span style="color:#F8F8F2">(</span><span style="color:#BD93F9">57</span><span style="color:#F8F8F2">, </span><span style="color:#E9F284">&quot;</span><span style="color:#F1FA8C">Marceline</span><span style="color:#E9F284">&quot;</span><span style="color:#F8F8F2">);</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre></div></div></div>
<p>These look mostly like regular function calls, but under the hood,
the client sends a request over the internet, which the database processes and responds to.</p>
<p>The <code>ReducerContext</code> is a reducer&#x27;s only mandatory parameter
and includes information about the caller&#x27;s <a href="#identity">identity</a>.
This can be used to authenticate the caller.</p>
<p>Reducers are run in their own separate and atomic <a href="https://en.wikipedia.org/wiki/Database_transaction" target="_blank" rel="noopener noreferrer">database transactions</a>.
When a reducer completes successfully, the changes the reducer has made,
such as inserting a table row, are <em>committed</em> to the database.
However, if the reducer instead returns an error, or throws an exception,
the database will instead reject the request and <em>revert</em> all those changes.
That is, reducers and transactions are all-or-nothing requests.
It&#x27;s not possible to keep the first half of a reducer&#x27;s changes and discard the last.</p>
<p>Transactions are only started by requests from outside the database.
When a reducer calls another reducer directly, as in the example below,
the changes in the called reducer does not happen in its own child transaction.
Instead, when the nested reducer gracefully errors,
and the overall reducer completes successfully,
the changes in the nested one are still persisted.</p>
<div class="theme-tabs-container tabs-container tabList_MbSD"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_Ssy3 tabs__item--active">Rust</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_Ssy3">C#</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_sydm"><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">#[spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#F8F8F2">reducer]</span></span>
<span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> hello</span><span style="color:#F8F8F2">(ctx</span><span style="color:#FF79C6">:</span><span style="color:#FF79C6"> &amp;</span><span style="color:#F8F8F2">spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-&gt;</span><span style="color:#8BE9FD;font-style:italic"> Result</span><span style="color:#F8F8F2">&lt;(), </span><span style="color:#8BE9FD;font-style:italic">String</span><span style="color:#F8F8F2">&gt; {</span></span>
<span class="line"><span style="color:#FF79C6"> if</span><span style="color:#50FA7B"> world</span><span style="color:#F8F8F2">(ctx)</span><span style="color:#FF79C6">.</span><span style="color:#50FA7B">is_err</span><span style="color:#F8F8F2">() {</span></span>
<span class="line"><span style="color:#50FA7B"> other_changes</span><span style="color:#F8F8F2">(ctx);</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2">#[spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#F8F8F2">reducer]</span></span>
<span class="line"><span style="color:#FF79C6">pub</span><span style="color:#FF79C6"> fn</span><span style="color:#50FA7B"> world</span><span style="color:#F8F8F2">(ctx</span><span style="color:#FF79C6">:</span><span style="color:#FF79C6"> &amp;</span><span style="color:#F8F8F2">spacetimedb</span><span style="color:#FF79C6">::</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-&gt;</span><span style="color:#8BE9FD;font-style:italic"> Result</span><span style="color:#F8F8F2">&lt;(), </span><span style="color:#8BE9FD;font-style:italic">String</span><span style="color:#F8F8F2">&gt; {</span></span>
<span class="line"><span style="color:#50FA7B"> clear_all_tables</span><span style="color:#F8F8F2">(ctx);</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span></code></pre><p>While SpacetimeDB doesn&#x27;t support nested transactions,
a reducer can <a href="https://docs.rs/spacetimedb/latest/spacetimedb/attr.reducer.html#scheduled-reducers" target="_blank" rel="noopener noreferrer">schedule another reducer</a> to run at an interval,
or at a specific time.</p></div><div role="tabpanel" class="tabItem_sydm" hidden=""><pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#F8F8F2">[</span><span style="color:#8BE9FD;font-style:italic">SpacetimeDB</span><span style="color:#F8F8F2">.</span><span style="color:#8BE9FD;font-style:italic">Reducer</span><span style="color:#F8F8F2">]</span></span>
<span class="line"><span style="color:#FF79C6">public</span><span style="color:#FF79C6"> static</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> Hello</span><span style="color:#F8F8F2">(</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#FFB86C;font-style:italic"> ctx</span><span style="color:#F8F8F2">)</span></span>
<span class="line"><span style="color:#F8F8F2">{</span></span>
<span class="line"><span style="color:#FF79C6"> if</span><span style="color:#F8F8F2">(</span><span style="color:#FF79C6">!</span><span style="color:#50FA7B">World</span><span style="color:#F8F8F2">(ctx))</span></span>
<span class="line"><span style="color:#F8F8F2"> {</span></span>
<span class="line"><span style="color:#50FA7B"> OtherChanges</span><span style="color:#F8F8F2">(ctx);</span></span>
<span class="line"><span style="color:#F8F8F2"> }</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F8F8F2">[</span><span style="color:#8BE9FD;font-style:italic">SpacetimeDB</span><span style="color:#F8F8F2">.</span><span style="color:#8BE9FD;font-style:italic">Reducer</span><span style="color:#F8F8F2">]</span></span>
<span class="line"><span style="color:#FF79C6">public</span><span style="color:#FF79C6"> static</span><span style="color:#FF79C6"> void</span><span style="color:#50FA7B"> World</span><span style="color:#F8F8F2">(</span><span style="color:#8BE9FD;font-style:italic">ReducerContext</span><span style="color:#FFB86C;font-style:italic"> ctx</span><span style="color:#F8F8F2">)</span></span>
<span class="line"><span style="color:#F8F8F2">{</span></span>
<span class="line"><span style="color:#50FA7B"> ClearAllTables</span><span style="color:#F8F8F2">(ctx);</span></span>
<span class="line"><span style="color:#6272A4"> // ...</span></span>
<span class="line"><span style="color:#F8F8F2">}</span></span></code></pre><p>While SpacetimeDB doesn&#x27;t support nested transactions,
a reducer can <a href="/modules/c-sharp#scheduled-reducers">schedule another reducer</a> to run at an interval,
or at a specific time.</p></div></div></div>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="client">Client<a href="#client" class="hash-link" aria-label="Direct link to Client" title="Direct link to Client" translate="no"></a></h3>
<p>A <strong>client</strong> is an application that connects to a <a href="#database">database</a>. A client logs in using an <a href="#identity">identity</a> and receives an <a href="#connectionid">connection id</a> to identify the connection. After that, it can call <a href="#reducer">reducers</a> and query public <a href="#table">tables</a>.</p>
<p>Clients are written using the <a href="#client-side-sdks">client-side SDKs</a>. The <code>spacetime</code> CLI tool allows automatically generating code that works with the client-side SDKs to talk to a particular database.</p>
<p>Clients are regular software applications that developers can choose how to deploy (through Steam, app stores, package managers, or any other software deployment method, depending on the needs of the application.)</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="identity">Identity<a href="#identity" class="hash-link" aria-label="Direct link to Identity" title="Direct link to Identity" translate="no"></a></h3>
<p>A SpacetimeDB <code>Identity</code> identifies someone interacting with a database. It is a long lived, public, globally valid identifier that will always refer to the same end user, even across different connections.</p>
<p>A user&#x27;s <code>Identity</code> is attached to every <a href="#reducer">reducer call</a> they make, and you can use this to decide what they are allowed to do.</p>
<p>Modules themselves also have Identities. When you <code>spacetime publish</code> a module, it will automatically be issued an <code>Identity</code> to distinguish it from other modules. Your client application will need to provide this <code>Identity</code> when connecting to the <a href="#host">host</a>.</p>
<p>Identities are issued using the <a href="https://openid.net/developers/how-connect-works/" target="_blank" rel="noopener noreferrer">OpenID Connect</a> specification. Database developers are responsible for issuing Identities to their end users. OpenID Connect lets users log in to these accounts through standard services like Google and Facebook.</p>
<p>Specifically, an identity is derived from the issuer and subject fields of a <a href="https://jwt.io/" target="_blank" rel="noopener noreferrer">JSON Web Token (JWT)</a> hashed together. The psuedocode for this is as follows:</p>
<pre tabindex="0" class="codeBlockStandalone_pMzE thin-scrollbar codeBlockContainer_HZVP theme-code-block" style="--prism-color:#bfc7d5;--prism-background-color:#292d3e"><code class="codeBlockLines_ckKi"><span class="line"><span style="color:#FF79C6">def</span><span style="color:#50FA7B"> identity_from_claims</span><span style="color:#F8F8F2">(</span><span style="color:#FFB86C;font-style:italic">issuer</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> str</span><span style="color:#F8F8F2">, </span><span style="color:#FFB86C;font-style:italic">subject</span><span style="color:#FF79C6">:</span><span style="color:#8BE9FD;font-style:italic"> str</span><span style="color:#F8F8F2">) </span><span style="color:#FF79C6">-&gt;</span><span style="color:#F8F8F2"> [u8; </span><span style="color:#BD93F9">32</span><span style="color:#F8F8F2">]:</span></span>
<span class="line"><span style="color:#F8F8F2"> hash1: [u8; </span><span style="color:#BD93F9">32</span><span style="color:#F8F8F2">] </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> blake3_hash(issuer </span><span style="color:#FF79C6">+</span><span style="color:#E9F284"> &quot;</span><span style="color:#F1FA8C">|</span><span style="color:#E9F284">&quot;</span><span style="color:#FF79C6"> +</span><span style="color:#F8F8F2"> subject)</span></span>
<span class="line"><span style="color:#F8F8F2"> id_hash: [u8; </span><span style="color:#BD93F9">26</span><span style="color:#F8F8F2">] </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> hash1[</span><span style="color:#FF79C6">:</span><span style="color:#BD93F9">26</span><span style="color:#F8F8F2">]</span></span>
<span class="line"><span style="color:#F8F8F2"> checksum_hash: [u8; </span><span style="color:#BD93F9">32</span><span style="color:#F8F8F2">] </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> blake3_hash([</span></span>
<span class="line"><span style="color:#FF79C6"> 0x</span><span style="color:#BD93F9">C2</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#FF79C6"> 0x</span><span style="color:#BD93F9">00</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#FF79C6"> *</span><span style="color:#F8F8F2">id_hash</span></span>
<span class="line"><span style="color:#F8F8F2"> ])</span></span>
<span class="line"><span style="color:#F8F8F2"> identity_big_endian_bytes: [u8; </span><span style="color:#BD93F9">32</span><span style="color:#F8F8F2">] </span><span style="color:#FF79C6">=</span><span style="color:#F8F8F2"> [</span></span>
<span class="line"><span style="color:#FF79C6"> 0x</span><span style="color:#BD93F9">C2</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#FF79C6"> 0x</span><span style="color:#BD93F9">00</span><span style="color:#F8F8F2">,</span></span>
<span class="line"><span style="color:#FF79C6"> *</span><span style="color:#F8F8F2">checksum_hash[</span><span style="color:#FF79C6">:</span><span style="color:#BD93F9">4</span><span style="color:#F8F8F2">],</span></span>
<span class="line"><span style="color:#FF79C6"> *</span><span style="color:#F8F8F2">id_hash</span></span>
<span class="line"><span style="color:#F8F8F2"> ]</span></span>
<span class="line"><span style="color:#FF79C6"> return</span><span style="color:#F8F8F2"> identity_big_endian_bytes</span></span></code></pre>
<p>You can obtain a JWT from our turnkey identity provider <a href="/spacetimeauth">SpacetimeAuth</a>, or you can get one from any OpenID Connect compliant identity provider.</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="connectionid">ConnectionId<a href="#connectionid" class="hash-link" aria-label="Direct link to ConnectionId" title="Direct link to ConnectionId" translate="no"></a></h3>
<p>A <code>ConnectionId</code> identifies client connections to a SpacetimeDB database.</p>
<p>A user has a single <a href="#identity"><code>Identity</code></a>, but may open multiple connections to your database. Each of these will receive a unique <code>ConnectionId</code>.</p>
<h3 class="anchor anchorWithStickyNavbar_wKCU" id="energy">Energy<a href="#energy" class="hash-link" aria-label="Direct link to Energy" title="Direct link to Energy" translate="no"></a></h3>
<p><strong>Energy</strong> is the currency used to pay for data storage and compute operations in a SpacetimeDB host.</p>
<h2 class="anchor anchorWithStickyNavbar_wKCU" id="faq">FAQ<a href="#faq" class="hash-link" aria-label="Direct link to FAQ" title="Direct link to FAQ" translate="no"></a></h2>
<ol>
<li>
<p>What is SpacetimeDB?
It&#x27;s a cloud platform within a database that&#x27;s fast enough to run real-time games.</p>
</li>
<li>
<p>How do I use SpacetimeDB?
Install the <code>spacetime</code> command line tool, choose your favorite language, import the SpacetimeDB library, write your module, compile it to WebAssembly, and upload it to the SpacetimeDB cloud platform. Once it&#x27;s uploaded you can call functions directly on your application and subscribe to changes in application state.</p>
</li>
<li>
<p>How do I get/install SpacetimeDB?
Just install our command line tool and then upload your application to the cloud.</p>
</li>
<li>
<p>How do I create a new database with SpacetimeDB?
Follow our <a href="/getting-started">Quick Start</a> guide!</p>
</li>
<li>
<p>How do I create a Unity game with SpacetimeDB?
Follow our <a href="/unity">Unity Tutorial</a> guide!</p>
</li>
</ol></div></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--next" href="/getting-started"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Getting Started</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_Ea_L thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#installation" class="table-of-contents__link toc-highlight">Installation</a></li><li><a href="#what-is-spacetimedb" class="table-of-contents__link toc-highlight">What is SpacetimeDB?</a></li><li><a href="#application-workflow-preview" class="table-of-contents__link toc-highlight">Application Workflow Preview</a></li><li><a href="#state-mirroring" class="table-of-contents__link toc-highlight">State Mirroring</a></li><li><a href="#language-support" class="table-of-contents__link toc-highlight">Language Support</a><ul><li><a href="#module-libraries" class="table-of-contents__link toc-highlight">Module Libraries</a></li><li><a href="#client-side-sdks" class="table-of-contents__link toc-highlight">Client-side SDKs</a></li><li><a href="#unity" class="table-of-contents__link toc-highlight">Unity</a></li></ul></li><li><a href="#key-architectural-concepts" class="table-of-contents__link toc-highlight">Key architectural concepts</a><ul><li><a href="#host" class="table-of-contents__link toc-highlight">Host</a></li><li><a href="#database" class="table-of-contents__link toc-highlight">Database</a></li><li><a href="#table" class="table-of-contents__link toc-highlight">Table</a></li><li><a href="#reducer" class="table-of-contents__link toc-highlight">Reducer</a></li><li><a href="#client" class="table-of-contents__link toc-highlight">Client</a></li><li><a href="#identity" class="table-of-contents__link toc-highlight">Identity</a></li><li><a href="#connectionid" class="table-of-contents__link toc-highlight">ConnectionId</a></li><li><a href="#energy" class="table-of-contents__link toc-highlight">Energy</a></li></ul></li><li><a href="#faq" class="table-of-contents__link toc-highlight">FAQ</a></li></ul></div></div></div></div></main></div></div></div><footer class="theme-layout-footer footer"><div class="container container-fluid"></div></footer></div>
</body>
</html>