MessagingService has always been unreliable and would drop messages. After some research into erasure coding, I built ReliableMessagingService, a wrapper that uses Random Linear Network Coding (RLNC) to handle packet loss.
GitHub: XoifaiI/ReliableMessagingService
Quick Example
local Start = 0
local ReliableMessagingService = require(game.ReplicatedStorage.ReliableMessagingService)
local RMS = ReliableMessagingService.New()
-- Subscribe to a topic
RMS:SubscribeAsync("GameEvents", function(Data: buffer)
print("Received:", buffer.tostring(Data), os.clock() - Start)
end)
local Success, Error = RMS:PublishAsync("GameEvents", buffer.fromstring("Hello, World!"))
if not Success then
warn("Failed to publish:", Error)
else
Start = os.clock()
end
-- Unsubscribe when done
RMS:Unsubscribe("GameEvents")
-- Clean up the service
RMS:Destroy()
How It Works
MessagingService has “best effort” delivery, messages can be dropped. ReliableMessagingService fixes this:
- Your message gets split into pieces (default: 8 pieces)
- Each piece is encoded using RLNC, they become “coded combinations” of your data
- Extra pieces are sent (default: 50% redundancy = 12 total pieces)
- Receiver only needs any 8 pieces to reconstruct, regardless of which ones arrive
Think of it like a puzzle where any 8 out of 12 pieces can reconstruct the full image. This tolerates up to 33% packet loss.
Also includes Zstd compression and automatic retry logic with exponential backoff that actually backs off cough cough Kohl.
Configuration
local RMS = ReliableMessagingService.New({
PieceCount = 8, -- Split into 8 pieces
RedundancyFactor = 1.5, -- Send 50% extra (12 total)
EnableCompression = true, -- Zstd compression
})
FAQ
Common Questions
“Why not just retry with exponential backoff?”
You still need to detect failures and wait for round trips. RLNC sends redundancy upfront with zero additional latency. Pick the right tool for your use case, simple retries work fine for some messages.
“12 messages instead of 1 is wasteful”
That’s how redundancy works. You’re trading ~1% of your rate limit budget for delivery guarantees. If your use case doesn’t need that, use vanilla MessagingService.
“Why not use MemoryStore/DataStores?”
Different tools. MemoryStore requires polling (wasted requests), DataStores have 50-500ms latency and tighter rate limits (60 + players x 10 vs 600 + players x 240). MessagingService is designed for real time events.
“MessagingService rarely drops messages”
From Roblox docs: “Delivery is best effort and not guaranteed. Make sure to architect your experience so delivery failures are not critical.”
“What about crashes/MessagingService downtime?”
No system can guarantee delivery if the underlying service is down or processes crash mid send. RLNC guarantees reconstruction given enough pieces arrive, not that pieces will always be sent. Same limitation as any messaging system. You could create a queue that stores the messages until they can be sent, but thats an entirely different system.
Notes
This library is tested and used in production, but do your own testing for your use case. Report bugs on GitHub or here. The library respects MessagingService rate limits and uses 1.5x bandwidth by default (12 messages vs 8 with redundancy).
