The Tina Data Layer provides a GraphQL API that serves Markdown and JSON files backed by a database. You can think of the database as more of an ephemeral cache, since the single source of truth for your content is really your Markdown/JSON files.

TinaCMS implements this database layer between the Tina GraphQL API and the underlying Git repository. This data layer buffers requests between TinaCloud and GitHub resulting in improved editing performance with TinaCMS.
Primary benefits of the Data Layer include:
It also enables additional capabilities such as:
Your Markdown files are the source of truth, but TinaCMS still requires the Data Layer to enable features like search, pagination, and references between Markdown files. Without it, every query would need to read and parse files directly from the filesystem or Git, which doesn't scale.
Since the Data Layer provides an API, you can fetch your content like you would with a traditional headless CMS.
Under the hood, the Data Layer has two key components:
When a GraphQL query comes in, TinaCMS reads from the indexed database rather than from raw files. This is what makes sorting, filtering, and pagination fast.
When you run tinacms dev, the Data Layer starts automatically with no configuration needed. It uses an in-memory database and reads files directly from your filesystem. A file watcher keeps the index up to date as you edit, so changes appear instantly.
TinaCloud provides the Data Layer for you as a fully hosted service.
It syncs with your GitHub repository via webhooks and maintains the index automatically. Each project gets its own GraphQL endpoint.
You can also host your own Data Layer as an alternative.
Indexing is the process of scanning your content files and storing them in the database so they can be queried. The index includes:
TinaCloud: The index updates incrementally every time a push is made to your GitHub repository (via webhooks). Only the changed files are re-indexed, so this is fast. A full re-index is triggered when:
tina/config.{ts,js} changesSelf-hosted: Indexing occurs when your site is built. Content updates made by editors through Tina are immediately reflected, but edits made directly to GitHub outside of Tina won't appear until the next build.
Local dev: The file watcher re-indexes files as soon as they change on disk.
Each Git branch has its own separate index. This means content on a feature branch won't affect your production branch, and vice versa.
In rare circumstances, the GitHub webhook connecting your repository to TinaCloud may be disrupted. If the webhook does not execute, TinaCloud may become out of sync with your GitHub repository.
Use the Refresh Webhooks button to re-initialize the webhook.
In some cases, TinaCloud's repository cache may become out of sync with your GitHub repository which might result in changes being present in your repository but not in TinaCMS. Generally this should only happen if there is a problem with the GitHub webhook. If this does occur, you can re-index the branch that is out of sync, restoring it to the current state of your repository. This will discard any updates in the branch in TinaCloud that haven't been pushed to your repository.
Use the Refresh Webhooks button to re-initialize the webhook.
Sometimes, you may find that a branch isn't indexed in TinaCloud. This can happen due to intermittent issues with GitHub. Alternatively, it can occur if you have existing branches from before connecting to TinaCloud. If you try to access a branch that hasn't been indexed, you'll see an error message indicating that the branch is unindexed.
See the Troubleshooting guide for a short walkthrough.
Using "Reindex" on a branch will discard any changes in TinaCloud that haven't been pushed to your repository for that branch. If you need to export your unsaved content from TinaCloud, you can use the Export Branch button to export the current state of your repository to a new branch.
The Data Layer is designed so that it can be hosted as a Serverless function alongside your site (with Vercel/Netlify functions, for example). You can also host it separately wherever you like.
When self-hosting, you need to provide two things:
mongodb-level) — for traditional database deploymentsupstash-redis-level) — for serverless deployments (e.g. Vercel KV)The database adapter is pluggable, so custom implementations are possible.
Common reasons for self-hosting include:
To learn more about self-hosting, see the Self-Hosted Overview.