ReliableMessagingService | RLNC Based Reliable Messaging

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:

  1. Your message gets split into pieces (default: 8 pieces)
  2. Each piece is encoded using RLNC, they become “coded combinations” of your data
  3. Extra pieces are sent (default: 50% redundancy = 12 total pieces)
  4. 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).

20 Likes

Been messing around with how it handles failures and a bunch of possible edge cases like sending pieces after the message has succeeded and making sure if messaging service is down there’s no memory leaks or more edge cases… I also got the RLNC module running about 700% faster with a bit more memory usage for look up tables

1 Like

Wow perfect timing Announcing Messaging Service Observability Dashboard

Any idea why the service is so slow sometimes? Some messages, even those with more information, are received in 0.5-1 second, but others take up to 2 seconds.

Another thing, it says it sent 2 messages in the last 7 days and I received 2 as well. Strange, I’ve sent many more messages in the last week (my game uses a custom matchmaking system).

Looks like the dashboard is a bit buggy some people are getting negative messages :thinking:

Yes, 2 seconds is completely normal for RLNC-based messaging in Roblox. The code sends pieces sequentially (12 pieces with default settings: 8 pieces x 1.5 redundancy), and each PublishAsync call has network latency of say 50-200ms. That’s 1.2-1.8 seconds just for sending, plus MessagingService delivery time. If you need faster delivery, reduce RedundancyFactor to 1.2 or PieceCount to 4, it’s a trade off between reliability (slower but more resilient) versus speed (faster but higher chance of message loss

Could also plop a warn inside RetryAsync to see if maybe messaging service is throwing alot of errors


I’ve randomly gotten some wack errors while testing

1 Like