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:
| Field | Assigned by | Purpose |
|---|---|---|
nonce | Client | Identifies one logical send across retries. It is unique within a channel. |
seq | Relay | Defines 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
- REST and WebSocket sends use the same message write path.
- Tenant resources stay inside the tenant’s PostgreSQL schema.
- The database assigns a channel-local
seqin the message transaction. - 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.