> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.hyjal.cloud/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.hyjal.cloud/_mcp/server.

# Store state with Hyjal Tables

> Create a Hyjal Table in the Console, query it from an API through the Database Door, and watch edits appear live in the Console grid.

This tutorial creates a [Hyjal Table](/data/hyjal-tables) in the Console, reads
and writes it from the `api` Resource through the Door, and watches Console
edits appear live in your API responses. Hyjal Tables are per-Project relational
tables stored in the Project [Bucket](/data/buckets), so you get app state
without provisioning an external database.

Time: about fifteen minutes. You need the [`hyjal` CLI](/reference/cli), a
logged-in session, and the `acme` Project with an `api` Resource.

## 1. Create a table in the Console

Open the Project in the [Console](/get-started/console/tables-view) and select
the **Tables** tab. Create a table named `notes` with these columns:

| Column       | Type      | Notes           |
| ------------ | --------- | --------------- |
| `id`         | integer   | primary key     |
| `body`       | text      |                 |
| `created_at` | timestamp | default `now()` |

The grid appears empty, ready for rows. See
[Create tables](/data/tables/create-tables) for the full column-type reference.

## 2. Add a row in the grid

In the `notes` grid, add a row with `body` set to `first note`. The grid writes
it immediately. Hyjal Tables use single-writer semantics per table group, so the
Console edit and your API share one consistent view.

## 3. Query the table from your API

Read the table from the `api` Resource through the Door. The Door exposes scoped
SQL over HTTP; the `hyjal-db` client handles the request.

```go
// api/main.go
package main

import (
	"encoding/json"
	"net/http"

	"github.com/hyjal/hyjal-db-go"
)

func handler(w http.ResponseWriter, r *http.Request) {
	db := hyjaldb.Tables() // Door client, no credentials to manage

	rows, _ := db.Query(r.Context(),
		"SELECT id, body, created_at FROM notes ORDER BY created_at DESC")

	w.Header().Set("content-type", "application/json")
	json.NewEncoder(w).Encode(rows)
}
```

The Door is a host-provided capability, so there is no connection string to
allowlist and no secret to set for Tables access: the platform scopes it to
your Project.

## 4. Deploy and read the row

```bash
$ hyjal deploy
Building resource api (lane: go)...
  tinygo build -target=wasip2 ✓
Uploading artifact... digest sha256:c40a72…8db1
Applying policy... ✓
Flipping route... ✓

Deployed acme/api
```

Call the endpoint. The row you added in the grid appears in the response:

```bash
$ curl https://api--acme.hyjal.cloud
[{"id":1,"body":"first note","created_at":"2026-07-13T17:10:22Z"}]
```

## 5. Watch edits appear live

Add a second row in the Console grid with `body` set to `second note`. Call the
endpoint again, no redeploy:

```bash
$ curl https://api--acme.hyjal.cloud
[{"id":2,"body":"second note","created_at":"2026-07-13T17:12:41Z"},
 {"id":1,"body":"first note","created_at":"2026-07-13T17:10:22Z"}]
```

The Console grid and your API read the same table. Reads scale with the fleet,
so every instance sees the write.

## 6. Write from the API

Writing back from the API shows up in the grid the same way. Add an insert path:

```go
db.Exec(r.Context(),
	"INSERT INTO notes (body) VALUES ($1)", "note from the api")
```

After a request hits that path, the new row appears in the Console `notes` grid
on the next refresh.

## What you built

* A `notes` Hyjal Table created and edited in the Console grid.
* An `api` Resource that reads and writes the table through the Door.
* A live loop where Console edits and API writes share one consistent view.

## Next steps

* Query patterns and types: [Hyjal Tables](/data/hyjal-tables)
* Edit and manage data in the Console: [Edit in Console](/data/tables/edit-in-console)
* Import and export table data: [Import and export](/data/tables/import-export)