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

# Multiple Instances

> Run several servers of one agent over one PostgreSQL database with a2a-sdk's cluster mode.

An agent server keeps its tasks in PostgreSQL when `POSTGRES_URL` is set.
In that mode the server runs [a2a-sdk](https://github.com/a2aproject/a2a-python)'s
cluster mode, and any number of servers of one agent can share the database:
any of them executes, follows and cancels any task.

Without `POSTGRES_URL` tasks are kept in memory, in one process. Run a single
server then: a second one shares nothing with the first.

## Requirements

| Requirement | Why |
| - | - |
| Every server of the agent sets the same `POSTGRES_URL` | Tasks, their versions and the event journal live there. |
| Framework state in the same database | The next turn of a task can run on any server. The SDK's LangGraph checkpointer and ADK session service use `POSTGRES_URL` - see [Checkpointing](/sdk/langgraph/guides/checkpointing) and [Session storage](/sdk/google-adk/guides/session-storage). |
| One SDK version across the servers | Upgrading from a release that used task claims runs migration `008`, which drops them. Stop every server of the agent before the first new one starts. |

## How requests are served

| Request | What happens |
| - | - |
| `SendMessage`, `SendStreamingMessage` | The server that receives it executes the turn, from the stored task. A task paused for input is resumed on whichever server receives the answer. |
| `SubscribeToTask`, task running on this server | The stream comes from the running execution. |
| `SubscribeToTask`, task running on another server | The stored task first, then the task's events from the database journal, until the task stops. The journal is polled every 0.5 seconds. |
| `SubscribeToTask`, task with an outcome | `UnsupportedOperationError` (`-32004`). Read the result with `GetTask`. |
| `CancelTask`, task running on this server | Cancelled through the agent's cancel handler. |
| `CancelTask`, any other task | `CANCELED` is written at once and the call answers. The server running the task stops it at its next write; the agent's cancel handler does not run there. |
| `GetTask`, `ListTasks` | Answered from the database by any server. |

Every stream opens and closes with a `Task`, whichever server serves it.

## Behaviour to plan for

* **Two executions of one task.** A second message sent to another server
  while the task is running is executed there. Each write carries the task's
  version, so the outcome that is written first stands; the other execution
  stops when it next writes. Send a task's next message after its current
  turn ends.
* **Live-only updates.** Response and thinking deltas and ephemeral progress
  are never stored, so a subscriber on another server does not receive them;
  it receives the stored messages, statuses and artifacts.
* **A server that dies.** Its tasks keep the state they had; nothing settles
  them on its own. Cancel such a task from any server. A server that shuts
  down in an orderly way settles its running tasks as `FAILED` with
  `aion:settledReason` set to `server_shutdown`.
* **The journal grows.** Every stored event is kept in `task_events`, also
  after its task is deleted.

## Database tables

| Table | Contents |
| - | - |
| `tasks`, `task_messages`, `task_artifacts` | The task, its history and its artifacts. |
| `task_versions` | One version per task, advanced by every write. |
| `task_events` | The event behind each write, read by subscribers on other servers. |

All of them are created in the `aion` schema by the SDK's migrations at
startup.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.