segment. Messages support threading via a self-referential parentId.
Who is this for? This reference describes the core chat server data model. It’s essential for data import, analytics integration, and understanding API response structures. For social entities (User, Community, Post, Comment, etc.), see the Social Data Model Reference.
Entity Reference
6 core entities with full field definitions, types, and relationship mappings
Patterns & Relationships
Message threading, channel–community linking, and feed structure
Enums & Import Tips
Enum values and 8 practical data import guidelines
Conventions
| Convention | Description |
|---|---|
| Triple-ID pattern | Most entities expose three IDs: a primary {entity}Id, a {entity}PublicId (stable external identifier), and a {entity}InternalId (database-level reference). For joins, prefer public IDs. |
| Soft delete | Nearly every entity has an isDeleted boolean. Deleted records remain in the database with isDeleted: true. Filter these out unless you specifically need deletion history. |
| Timestamps | createdAt and updatedAt (ISO 8601 date-time) are present on all entities. Some also have editedAt. |
| Metadata | A freeform metadata object is available on most entities for custom fields. |
| Flagging | flagCount (number of reports) and hashFlag (bloom-filter structure) track moderation state on messages. Channels bubble up flags via hasFlaggedMessage. |
Entity-Relationship Diagram
The following diagram shows the core entities and their relationships in the chat module.Entity Reference
Channel
Channel
A chat room, conversation, or group. Channels are the top-level container for messaging. Every community has a 1:1 backing channel. Channels can be standard (open), private, direct conversations, broadcast, community-backed, or live (attached to a room).
Relationships:
| Field | Type | Description |
|---|---|---|
channelId | string | Primary key. Public channel identifier. |
channelInternalId | string | Internal database identifier. |
channelPublicId | string | Public identifier (same as channelId). |
type | enum | standard | private | conversation | broadcast | community | live. |
displayName | string | Channel display name. |
isDistinct | boolean | If true, reuses existing channel for the same user set (conversations). |
tags | string[] | Tags for filtering/categorization. |
metadata | object | Arbitrary custom fields. |
avatarFileId | string | FK → File. Channel avatar image. |
lastActivity | date-time | Timestamp of last activity (message, event, etc.). |
memberCount | integer | (Computed) Number of members. |
messageCount | integer | (Computed) Number of messages. |
moderatorMemberCount | integer | Count of moderator members. |
isPublic | boolean | Whether channel is publicly listed. |
notificationMode | enum | default | silent | subscribe. |
isMuted | boolean | (Computed) Whether the channel is currently muted (based on muteTimeout). |
muteTimeout | date-time | When the channel-level mute expires. |
isRateLimited | boolean | (Computed) Whether rate limiting is active (based on rateLimitTimeout). |
rateLimit | number | Maximum messages per rate limit window. |
rateLimitWindow | number | Rate limit window in milliseconds. |
rateLimitTimeout | date-time | When the current rate limit expires. |
messageAutoDeleteEnabled | boolean | Whether auto-delete by flag threshold is enabled. |
autoDeleteMessageByFlagLimit | number | Flag count threshold for auto-deletion. |
messagePreviewId | string | (Computed) ID of the latest message preview. |
attachedTo | object | Linked resources: {postId, videoStreamId, roomId}. |
isDeleted | boolean | Soft-delete flag. |
createdAt | date-time | Creation timestamp. |
updatedAt | date-time | Last update timestamp. |
1:1→ Community (community-type channels back a community; see Channel ↔ Community Relationship)1:N→ ChannelUser (members)1:N→ MessageFeed (message threads within the channel)0:1→ Room (live-type channels are attached to a room viaattachedTo.roomId)0:1→ File (avatar viaavatarFileId)
ChannelUser (Member)
ChannelUser (Member)
The join entity between User and Channel. Represents a user’s membership, roles, and read state within a channel.
Relationships:
| Field | Type | Description |
|---|---|---|
userId | string | FK → User. User’s public ID. |
userInternalId | string | User’s internal ID. |
userPublicId | string | User’s public ID. |
channelId | string | FK → Channel. Channel’s public ID. |
channelInternalId | string | Channel’s internal ID. |
channelPublicId | string | Channel’s public ID. |
membership | enum | none | member | banned. |
roles | string[] | Role public IDs assigned within this channel. |
permissions | string[] | Resolved permissions from roles. |
isBanned | boolean | (Computed) true when membership = "banned". |
isMuted | boolean | (Computed) true when muteTimeout > now. |
muteTimeout | date-time | When the user-level mute expires in this channel. |
readToSegment | number | Last-read message segment (read cursor). |
lastMentionedSegment | number | Segment of last @mention for this user. |
lastActivity | date-time | User’s last activity in the channel. |
createdAt | date-time | Record creation timestamp. |
updatedAt | date-time | Last update timestamp. |
N:1→ UserN:1→ Channel- Composite key: (
userId,channelId)
Message
Message
A message within a channel. Messages belong to a MessageFeed and support threading (replies). Each message is stored as its own document.
Relationships:
| Field | Type | Description |
|---|---|---|
messageId | string | Primary key. Internal message ID. |
publicId | string | Public-facing message ID. |
channelId | string | FK → Channel. Channel this message belongs to. |
channelPublicId | string | Channel’s public ID. |
messageFeedId | string | FK → MessageFeed. The feed/thread containing this message. |
parentId | string | FK → Message (self). Parent message ID for replies. null for top-level messages. |
creatorId | string | FK → User. Creator’s internal ID. |
creatorPublicId | string | Creator’s public ID. |
dataType | enum | text | image | video | file | audio | custom | json | imagemap. |
data | object | Message payload. For media types, includes fileId and optionally thumbnailFileId. |
segment | number | Ordering position within the feed. |
tags | string[] | Tags associated with this message. |
metadata | object | Arbitrary custom fields. |
mentionedUsers | array | Mentioned users: [{type: "user"|"channel", userIds: [...]}]. |
childCount | integer | Number of direct replies. |
reactions | object | Map of reactionName → count. |
reactionCount | integer | Total reaction count. |
myReactions | string[] | Current user’s reaction names. |
flagCount | integer | Number of moderation reports. |
hashFlag | object | (Computed) Bloom-filter flag structure. |
editedAt | date-time | Last content edit timestamp. |
isDeleted | boolean | Soft-delete flag. |
createdAt | date-time | Creation timestamp. |
updatedAt | date-time | Last update timestamp. |
Threading model: See Message Threading Model below for details on how replies work.
N:1→ User (creator viacreatorId)N:1→ Channel (viachannelId)N:1→ MessageFeed (viamessageFeedId)1:N→ Message (replies viaparentId, self-referential)1:N→ Reaction (viareaction.referenceIdwherereferenceType = "message")0:1→ File (attachment viadata.fileId)
MessageFeed
MessageFeed
A message thread/feed within a channel. Each channel has one or more message feeds. The feed tracks the latest message and provides a message preview for UI display.
Relationships:
| Field | Type | Description |
|---|---|---|
messageFeedId | string | Primary key. |
channelId | string | FK → Channel. The channel this feed belongs to. |
channelPublicId | string | Channel’s public ID. |
channelType | enum | Channel type: standard | private | conversation | broadcast | community | live. |
name | string | Feed display name. |
creatorId | string | FK → User. Feed creator’s internal ID. |
creatorPublicId | string | Creator’s public ID. |
lastMessageId | string | FK → Message. Most recent message. |
lastMessageTimestamp | date-time | Timestamp of the most recent message. |
messagePreviewId | string | (Computed) ID of the preview message. |
childCount | integer | Number of messages in this feed. |
isDeleted | boolean | Soft-delete flag. |
editedAt | date-time | Last metadata edit timestamp. |
createdAt | date-time | Creation timestamp. |
updatedAt | date-time | Last update timestamp. |
N:1→ Channel (viachannelId)N:1→ User (creator viacreatorId)1:N→ Message (messages reference feed viamessageFeedId)
Reaction
Reaction
Tracks reactions (likes, love, etc.) on messages. Each reaction is stored as its own document — one document per user-reaction-reference combination. Reactions use a polymorphic reference that supports multiple content types across both chat and social modules.
Relationships:
| Field | Type | Description |
|---|---|---|
reactionId | string | Primary key. Unique reaction instance ID. |
reactionName | string | Freeform name, e.g., "like", "love", "wow". |
userId | string | FK → User. Who reacted. |
userInternalId | string | Reactor’s internal ID. |
referenceId | string | FK → Message (in chat context). The content being reacted to. |
referenceType | enum | post | comment | story | message. For chat, this is always message. |
createdAt | date-time | When the reaction was added. |
updatedAt | date-time | When the reaction was last updated. |
Reaction names are freeform strings, not a fixed enum. The
reactions field on Message aggregates these as {reactionName: count}. The same Reaction entity is shared across both social and chat modules — only the referenceType differs.N:1→ Message (whenreferenceType = "message")N:1→ User (viauserId)
File
File
An uploaded media file (image, video, audio, or generic file). Files are referenced by messages and channels via
Relationships:
Referenced by: Message (
fileId. The File entity is shared across both social and chat modules.| Field | Type | Description |
|---|---|---|
fileId | string | Primary key. Cloud storage key. |
fileUrl | string | HTTP download URL. |
type | enum | image | file | video | audio | clip. |
accessType | enum | public (open download) | network (requires authentication). |
altText | string | Alternative text (max 180 chars). |
feedType | string | Feed type associated with this file. |
status | enum | uploaded | transcoding | transcoded | transcodeFailed. Processing status (mainly for video/audio). |
isDeleted | boolean | Soft-delete flag. |
videoUrl | object | Video URLs by resolution: {1080p, 720p, 480p, 360p, original}. Present for video files. |
attributes.name | string | Original file name. |
attributes.extension | string | File extension/format. |
attributes.size | number | File size in bytes. |
attributes.mimeType | string | MIME type. |
attributes.metadata | object | (Schemaless) Additional metadata. May contain width, height, exif, gps if set by the uploading client, but these sub-fields are not enforced by the schema. |
createdAt | date-time | Upload timestamp. |
updatedAt | date-time | Last update timestamp. |
data.fileId, data.thumbnailFileId), Channel (avatarFileId).Message Threading Model
Messages support single-level threading within a message feed:Reconstructing Threads
- Query messages by
messageFeedId. - Top-level messages:
parentId = null. - Group replies by
parentId. - Order all messages by
segment.
Channel ↔ Community Relationship
Every community in the social module has a 1:1 backing channel withtype = "community". This relationship connects the social and chat modules:
Cross-module linking: The Community entity stores a
channelId foreign key pointing to its backing channel. Community-type channels inherit the community’s membership — a user who is a community member is also a channel member. When importing data that spans both modules, ensure the Community’s channelId FK is correctly linked.Key Enums Reference
Full Enums Table
Full Enums Table
| Enum | Values | Used By |
|---|---|---|
| Channel.type | standard, private, conversation, broadcast, community, live | Channel .type |
| Channel.notificationMode | default, silent, subscribe | Channel .notificationMode |
| ChannelUser.membership | none, member, banned | ChannelUser .membership |
| Message.dataType | text, image, video, file, audio, custom, json, imagemap | Message .dataType |
| Reaction.referenceType | post, comment, story, message | Reaction .referenceType |
Data Import Tips
1. ID Resolution
1. ID Resolution
Most entities expose three IDs (
channelId, channelPublicId, channelInternalId). For joining data across entities, use the public ID — these are the values used in foreign key references. Internal IDs are database-level identifiers and may not appear in all API responses.2. Channel ↔ Community Linking
2. Channel ↔ Community Linking
Every community has a 1:1 backing channel (with
type = "community"). When importing both communities and channels, ensure corresponding records are linked. The community stores a channelId foreign key.3. Message Ordering by Segment
3. Message Ordering by Segment
Messages within a feed are ordered by
segment (a monotonically increasing integer). Preserve segment ordering during import to maintain correct message sequence. Each feed maintains its own independent segment counter.4. ChannelUser Composite Key
4. ChannelUser Composite Key
The ChannelUser entity uses a composite key of (
userId, channelId). When importing, deduplicate on both fields to avoid creating duplicate membership records.5. Computed Fields — Do Not Import
5. Computed Fields — Do Not Import
Several fields are derived at read time and should not be imported as stored values:
Channel.isMuted— derived frommuteTimeout > now.Channel.isRateLimited— derived fromrateLimitTimeout > now.Channel.memberCount/messageCount— aggregated from related records.ChannelUser.isBanned— derived frommembership = "banned".ChannelUser.isMuted— derived frommuteTimeout > now.Message.myReactions— derived per-request for the current user.MessageFeed.messagePreviewId— derived from latest message.
6. Filtering Deleted Records
6. Filtering Deleted Records
Soft-deleted records have
isDeleted: true. Exclude these by default for analytics unless you need deletion history.7. Reactions on Messages
7. Reactions on Messages
Message reactions follow the same model as social reactions (see Social Data Model Reference). Each reaction is stored as a separate document with
referenceType = "message" and referenceId pointing to the message. The reactions object on Message provides pre-aggregated {name: count} maps.8. Message Threading
8. Message Threading
To get only top-level messages (not replies), filter by
parentId = null. To reconstruct threads, group replies by parentId and order by segment. See Message Threading Model for the full pattern.