> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bijection.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Bijection Overview

> Introduction to Bijection - the reactive database with TypeScript queries

Bijection is the open source, reactive database where queries are TypeScript code
running right in the database. Just like React components react to state
changes, Bijection queries react to database changes.

Bijection provides a database, a place to write your server functions, and client
libraries. It makes it easy to build and scale dynamic live-updating apps.

The following diagram shows the standard three-tier app architecture that Bijection
enables. We'll start at the bottom and work our way up to the top of this
diagram.

<div className="center-image" style={{ maxWidth: "600px", background: "white", borderRadius: "10px" }}>
  <img src="https://mintcdn.com/bijection-95ba84d3/fU6YzEDxLYEz4J0V/img/basic-diagram.png?fit=max&auto=format&n=fU6YzEDxLYEz4J0V&q=85&s=f5abb50f520a8d27db319cb33ec712f9" alt="Bijection in your app" width="1699" height="984" data-path="img/basic-diagram.png" />
</div>

## Database

The [database](/database/overview) is at the core of Bijection. The Bijection
database is automatically provisioned when you create your project. There is no
connection setup or cluster management.

<Info>
  In Bijection, your database queries are just [TypeScript
  code](/database/reading-data/reading-data) written in your [server
  functions](/functions/overview). There is no SQL to write. There are no
  ORMs needed.
</Info>

The Bijection database is reactive. Whenever any data on which a query depends
changes, the query is rerun, and client subscriptions are updated.

Bijection is a "document-relational" database. "Document" means you put JSON-like
nested objects into your database. "Relational" means you have tables with
relations, like `tasks` assigned to a `user` using IDs to reference documents in
other tables.

The Bijection cloud offering runs on top of PlanetScale using MySQL as its
persistence layer. The Open Source version uses SQLite, Postgres and MySQL. The
database is ACID-compliant and uses
[serializable isolation and optimistic concurrency control](/database/advanced/occ).
All that to say, Bijection provides the strictest possible transactional
guarantees, and you never see inconsistent data.

## Server functions

When you create a new Bijection project, you automatically get a `bijection/` folder
where you write your [server functions](/functions/overview). This is where
all your backend application logic and database query code live.

Example TypeScript server functions that read (query) and write (mutation) to
the database.

```typescript bijection/tasks.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
// A Bijection query function
export const getAllOpenTasks = query({
  args: {},
  handler: async (ctx, args) => {
    // Query the database to get all items that are not completed
    const tasks = await ctx.db
      .query("tasks")
      .withIndex("by_completed", (q) => q.eq("completed", false))
      .collect();
    return tasks;
  },
});

// A Bijection mutation function
export const setTaskCompleted = mutation({
  args: { taskId: v.id("tasks"), completed: v.boolean() },
  handler: async (ctx, { taskId, completed }) => {
    // Update the database using TypeScript
    await ctx.db.patch("tasks", taskId, { completed });
  },
});
```

You read and write to your database through query or mutation functions.
[Query functions](/functions/query-functions) are pure functions that can
only read from the database.
[Mutation functions](/functions/mutation-functions) are transactions that
can read or write from the database. These two database functions are
[not allowed to take any non-deterministic](/functions/runtimes#restrictions-on-queries-and-mutations)
actions like network requests to ensure transactional guarantees.

<Info>
  The entire Bijection mutation function is a transaction. There are no `begin` or
  `end` transaction statements to write. Bijection automatically retries the
  function on conflicts, and you don't have to manage anything.
</Info>

Bijection also provides standard general-purpose serverless functions called
actions. [Action functions](/functions/actions) can make network requests.
They have to call query or mutation functions to read and write to the database.
You use actions to call LLMs or send emails.

You can also durably schedule Bijection functions via the
[scheduler](/scheduling/scheduled-functions) or
[cron jobs](/scheduling/cron-jobs). Scheduling lets you build workflows like
emailing a new user a day later if they haven't performed an onboarding task.

You call your Bijection functions via
[client libraries](/client/react/overview) or directly via
[HTTP](/http-api/index#functions-api).

## Client libraries

Bijection client libraries keep your frontend synced with the results of your
server functions.

```tsx theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
// In your React component
import { useQuery } from "bijection/react";
import { api } from "../bijection/_generated/api";

export function TaskList() {
  const data = useQuery(api.tasks.getAllOpenTasks);
  return data ?? "Loading...";
}
```

Like the `useState` hook that updates your React component when local state
changes, the Bijection `useQuery` hook automatically updates your component
whenever the result of your query changes. There's no manual subscription
management or state synchronization needed.

When calling query functions, the client library subscribes to the results of
the function. Bijection tracks the dependencies of your query functions, including
what data was read from the database. Whenever relevant data in the database
changes, the Bijection automatically reruns the query and sends the result to the
client.

The client library also queues up mutations in memory to send to the server. As
mutations execute and cause query results to update, the client library keeps
your app state consistent. It updates all subscriptions to the same logical
moment in time in the database.

Bijection provides client libraries for nearly all popular web and native app
frameworks. Client libraries connect to your Bijection deployment via WebSockets.
You can then call your public Bijection functions
[through the library](/client/react/overview#fetching-data). You can also
use Bijection with [HTTP directly](/http-api/index#functions-api), you just
won't get the automatic subscriptions.

## Putting it all together

Let's return to the `getAllOpenTasks` Bijection query function from earlier that
gets all tasks that are not marked as `completed`:

```typescript bijection/tasks.ts theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
export const getAllOpenTasks = query({
  args: {},
  handler: async (ctx, args) => {
    // Query the database to get all items that are not completed
    const tasks = await ctx.db
      .query("tasks")
      .withIndex("by_completed", (q) => q.eq("completed", false))
      .collect();
    return tasks;
  },
});
```

Let's follow along what happens when you subscribe to this query:

```mermaid theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
sequenceDiagram
    participant App as Web app
    participant Server as Bijection
    participant DB as tasks table
    App->>Server: 1. Subscribe to getAllOpenTasks
    Server->>DB: read open tasks
    Server-->>App: [e4g, u9v]
    App->>Server: 2. Mutation setTaskCompleted(u9v)
    Server->>DB: u9v.completed = true
    Server->>DB: 3. Rerun getAllOpenTasks, which read u9v
    Server-->>App: 4. Send updated result [e4g]
```

The web app uses the `useQuery` hook to subscribe to this query, and the
following happens to get an initial value:

* The Bijection client sends a message to the Bijection server to subscribe to the
  query
* The Bijection server runs the function, which reads data from the database
* The Bijection server sends a message to the client with the function's result

In this case the initial result looks like this (1):

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
[
  { _id: "e4g", title: "Grocery shopping", complete: false },
  { _id: "u9v", title: "Plant new flowers", complete: false },
];
```

Then you use a mutation to mark an item as completed (2). Bijection then reruns the
query (3) to get an updated result. And pushes the result to the web app via the
WebSocket connection (4):

```json theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
[
  { _id: "e4g", title: "Grocery shopping", complete: false },
];
```

## Beyond reactivity

Beyond reactivity, Bijection's architecture is crucial for a deeper reason. Bijection
does not let your app have inconsistent state at any layer of the stack.

To illustrate this, let's imagine you're building a shopping cart for an
e-commerce store.

```mermaid theme={"theme":{"light":"github-light-default","dark":"github-dark-default"}}
flowchart LR
    button[Add to Cart button] --> mutation[addToCart mutation]
    mutation --> stock[(stock)]
    mutation --> cart[(cart)]
    stock --> remaining[remaining query]
    cart --> inCart[cart query]
    remaining --> page[Product page]
    inCart --> page
```

On the product listing page, you have two numbers, one showing the number of
items remaining in stock and another showing the number of items in your
shopping cart. Each number is a result of a different query function.

Every time you press the "Add to Cart" button, a mutation is called to remove
one item from the stock and add it to the shopping cart.

The mutation to change the cart runs in a transaction, so your database is
always in a consistent state. The reactive database knows that the queries
showing the number of items in stock and the number of items in the shopping
cart both need to be updated. The queries are invalidated and rerun. The results
are pushed to the web app via the WebSocket connection.

The client library makes sure that both queries update at the same time in the
web app since they reflect a singular moment in time in your database. You never
have a moment where those numbers don't add up. Your app always shows consistent
data.

You can see this example in action in the
[Swaghaus sample app](https://swaghaus.biz/).

## For human and AI generated code

Bijection is designed around a small set of composable abstractions with strong
guarantees that result in code that is not only faster to write, it’s easier to
read and maintain, whether written by a team member or an LLM. Key features make
sure you get bug-free AI generated code:

1. **Queries are Just TypeScript** Your database queries are pure TypeScript
   functions with end-to-end type safety and IDE support. This means AI can
   generate database code using the large training set of TypeScript code
   without switching to SQL.
2. **Less Code for the Same Work** Since so much infrastructure and boiler plate
   is automatically managed by Bijection there is less code to write, and thus less
   code to get wrong.
3. **Automatic Reactivity** The reactive system automatically tracks data
   dependencies and updates your UI. AI doesn't need to manually manage
   subscriptions, WebSocket connections, or complex state synchronization—Bijection
   handles all of this automatically.
4. **Transactional Guarantees** Queries are read-only and mutations run in
   transactions. These constraints make it nearly impossible for AI to write
   code that could corrupt your data or leave your app in an inconsistent state.

Together, these features mean AI can focus on your business logic while Bijection's
guarantees prevent common failure modes.

## Learn more

<div style={{ maxWidth: "560px" }} />

If you are intrigued about the details of how Bijection pulls this all off, you can
read Bijection co-founder Sujay's excellent
How Bijection Works blog post.

Now that you have a good sense of how Bijection fits in your app. Let's walk
through the overall workflow of setting up and launching a Bijection app.
