GrabMd RiyadhProblem & solution
How we seamlessly migrated high volume real-time streaming traffic from one service to another with zero data loss and duplication
Summary
Grab migrated its stream-processing (write) functionality from an existing service into a separate service while handling 20,000 reads per second from 16 Kafka streams and writing to output streams and DynamoDB tables. The migration required gradual stream-by-stream rollout, production validation, and a no-downtime switchover; feature flags were rejected because deployment timing could cause loss, duplication, or inconsistent values. The team moved processing into shared /commons code, created temporary validation sinks, and scheduled each switchover with a shared map[string]time.Time, allowing both services to change writers at the same time. During each cutover, both services consumed streams, the old service stopped writing to resources, and monitoring continued before old consumption was removed; the result was zero data loss or duplication, no downtime, and completion in about three weeks. It was temporary and tested, but rolling back either service could create inconsistency if systems fell out of sync.
Context
The existing backend service combined read and write functionality, although the two operations had distinct scalability requirements. The migration also had to handle high-volume real-time traffic while avoiding data loss, duplication, downtime, and inconsistencies during switchover.
Approach / What changed
Stream-processing code was moved into shared /commons code used by both services. The new service wrote to temporary validation streams and DynamoDB tables during production monitoring, while a shared map[string]time.Time scheduled each stream's switchover. At the scheduled time, the new service began writing to main resources as the old service stopped, followed by continued monitoring and removal of old consumption.
Takeaways
Both services consumed incoming streams during validation, but only the old service wrote to the actual sink resources while the new service used temporary validation sinks.
A shared per-stream map[string]time.Time provided identical switchover timing in both services, avoiding overlap or gaps when changing the active writer.
The migration completed in about three weeks with zero reported data loss or duplication and no downtime, but rollback could cause inconsistency if the services fell out of sync.
Source and freshness
- Source
- engineering.grab.com
- Published
- Added to Yomu
- Last updated
Summaries are generated from the original by a language model. Check the original before relying on it.
Keep reading
Related reading
The Good Stuff
Paid picks we use ourselves. Links carry a referral code — a subscription through one earns us a commission at no extra cost to you.
The best engineering reads, once a week
One useful email. Unsubscribe anytime.