Search the complete documentation

Try idempotency, proposal lifecycle, authentication, or ordering.

Navigate Open
繁體中文
Browse documentation

Relay · Concepts

Relay concepts

Relay owns conversation transport. Your product supplies identity and business rules; Relay stores channels, membership, messages, and delivery state without learning your domain model.

Host product
  └─ tenant
      └─ channel
          ├─ members
          ├─ messages ordered by seq
          └─ read cursors

Tenant

A tenant is the isolation boundary. Relay stores each tenant’s conversation resources in a dedicated PostgreSQL schema named tenant_<uuid>.

The host decides when to create a tenant and how that tenant maps to its own account or organization. Relay does not infer this relationship.

User identity

Relay receives a user_id through a host-signed token. The host owns login, account state, roles, and the mapping from a business user to that identifier.

An agent or bot is also a user in Relay. It uses the same tenant and membership checks as a human user.

Channel and membership

A channel contains one ordered conversation. It stores a next_seq counter and may be closed with closed_at.

A member connects one user_id to one channel. Membership controls access to channel messages. Closing a channel prevents new messages but does not erase its history.

Message

Every message contains two identifiers with different jobs:

FieldAssigned byPurpose
nonceClientIdentifies one logical send across retries. It is unique within a channel.
seqRelayDefines the message’s position within the channel.

seq is assigned by the database in the message transaction. Client time does not determine message order.

Messages may also include parent_message_id, mentions, reactions, and attachments. These features keep the same tenant, membership, ordering, and idempotency boundaries.

Read cursor

Relay stores each member’s last_read_seq for a channel. A cursor refers to the server sequence, so it remains meaningful across reconnects and devices.

The host decides how unread state appears in its product. Relay provides transport state, not notification policy or interface behavior.

Four invariants

  1. REST and WebSocket sends use the same message write path.
  2. Tenant resources stay inside the tenant’s PostgreSQL schema.
  3. The database assigns a channel-local seq in the message transaction.
  4. Reusing (channel_id, nonce) returns the original message instead of creating another one.

Ownership boundary

Relay owns conversation transport: channel, member, message, reply, reaction, attachment, sequence, cursor, and delivery behavior.

The host owns business identity, business authorization, workflow, notification policy, and every fact outside the conversation contract. Relay never calls the host application API.

Next: authenticate a Relay request.