val statePluginFactory = StreamStatePluginFactory(
config = StatePluginConfig(
messageLimitConfig = MessageLimitConfig(
channelMessageLimits = setOf(
// Limit livestream channels to 500 messages in memory
ChannelMessageLimit(channelType = "livestream", baseLimit = 500),
// Limit messaging channels to 1000 messages in memory
ChannelMessageLimit(channelType = "messaging", baseLimit = 1000),
),
),
),
appContext = context,
)
ChatClient.Builder(apiKey, context)
.withPlugins(statePluginFactory)
.build()Livestream Chat
High-traffic channels like livestreams can generate thousands of messages per minute. The SDK provides configuration options to optimize memory usage and performance for these scenarios.
Message Limiting
The MessageLimitConfig allows you to control how many messages are kept in memory for different channel types. When the message count exceeds the configured limit, older messages are automatically trimmed from memory while keeping the most recent ones.
Configuration
Configure message limits when setting up the StatePlugin:
How It Works
- When the message count exceeds
baseLimit + 30(buffer), the SDK trims messages down tobaseLimit - Messages are sorted by creation time; only the most recent ones are kept
- Trimming only occurs when not loading older messages (to avoid interfering with pagination)
- If loading older messages causes the count to exceed the limit, the limit is temporarily increased by 1.5x
- The
endOfOlderMessagesflag is set tofalsewhen trimming occurs, indicating more messages are available but not yet loaded in memory - Messages are only removed from in-memory state, not from the local database
UI Integration
If you're using Jetpack Compose, the MessageList component works seamlessly with message limiting. Compose's LazyColumn only renders visible items, providing efficient virtualization automatically:
MessageList(
viewModel = messageListViewModel,
// Messages are automatically limited based on your MessageLimitConfig
)For custom implementations, observe the message state from ChannelState:
val channelState: StateFlow<ChannelState?> = chatClient.watchChannelAsState(cid, messageLimit = 30)
channelState
.filterNotNull()
.flatMapLatest { it.messages }
.collectLatest { messages ->
// Messages are already limited based on your configuration
updateUI(messages)
}Skipping Database Storage
For channels where message persistence is not needed (e.g., ephemeral livestream messages), you can configure the OfflinePlugin to skip database storage entirely. This reduces disk I/O and improves performance.
Configuration
Configure ignored channel types when setting up the OfflinePlugin:
val offlinePluginFactory = StreamOfflinePluginFactory(
appContext = context,
// Messages in these channel types won't be stored in the local database
ignoredChannelTypes = setOf("livestream"),
)
ChatClient.Builder(apiKey, context)
.withPlugins(statePluginFactory, offlinePluginFactory)
.build()Behavior
When a channel type is in ignoredChannelTypes:
- Messages are not persisted to the local database
- Reactions in these channels are not stored locally
- The channel still receives real-time updates via WebSocket
This is useful for high-volume channels where:
- Messages are ephemeral and don't need offline access
- Reducing database writes improves performance
- Storage space is a concern
Complete Setup Example
Here's a complete example combining both optimizations for a livestream use case:
// Configure state plugin with message limiting
val statePluginFactory = StreamStatePluginFactory(
config = StatePluginConfig(
messageLimitConfig = MessageLimitConfig(
channelMessageLimits = setOf(
ChannelMessageLimit(channelType = "livestream", baseLimit = 500),
),
),
),
appContext = context,
)
// Configure offline plugin to skip DB for livestream channels
val offlinePluginFactory = StreamOfflinePluginFactory(
appContext = context,
ignoredChannelTypes = setOf("livestream"),
)
// Build ChatClient with both plugins
ChatClient.Builder(apiKey, context)
.withPlugins(statePluginFactory, offlinePluginFactory)
.build()With this configuration:
- Livestream channels keep only the 500 most recent messages in memory
- Messages are not written to the local database
- Real-time updates continue to work normally
- Memory and disk usage remain controlled even with high message volume