Search code examples
google-cloud-firestoresynchronizationreal-time-updates

How to achieve realtime synchronization between my own back-end and my mobile app?


I'm a bit jealous of services like Google Cloud Firestore which achieve realtime sync between mobile app (or web app) and back-end. It makes me see plain-old HTTP GET back-ends as prehistoric.

I'm wondering if, in 2O19, it exists quite simple/scalable solutions/frameworks to achieve this on my own back-end. I've heard about sockets but it looks costly and quite difficult to setup (maybe I'm wrong). Silent notifications maybe? (but again it adds a layer of complexity of managing that and we don't have 100% confidence that every notification will reach its target).

I understand conflicts is the most sensitive topic so even a readonly solution (only back-end can modify entities) would be great.


Solution

  • There are solutions for real-time synchronization of data. Most of them use WebSockets or SSE (Server Side Events) for transportation, which also goes for Google Cloud Firestore. And many of the existing solutions are databases with synchronization capabilities, just like Firestore. But there are other options too.

    Existing solutions

    Assuming you are not looking for push solutions, such as PubNub or Pusher, but rather seamless synchronization of data, then I can mention a few to get you started:

    Example using Resgate

    Realtime API gateways such as Resgate (which I am clearly baised towards :) ), lets you write (micro)services in the language of your choice in a similar fashion as you would write an ordinary HTTP webservice. The gateway then exposes the resources in a REST and realtime API, and keeps the clients synchronized.

    C# service using ResgateIO.Service

    ResService service = new ResService("example");
    service.AddHandler("mymodel", new DynamicHandler()
        .SetGet(r => r.Model(new {
            message = "Hello, World!",
        }))
        .SetAccess(r => r.AccessGranted()));
    service.Serve("nats://127.0.0.1:4222");
    

    But with the addition that you can send events to update and synchronize all clients:

    service.With("example.mymodel", r => r.ChangeEvent(new Dictionary<string, object> {
        { "message", "Hello, StackOverflow!" }
    }));
    

    The client can then fetch the data, and listen for updates:

    Javascript client using ResClient

    let client = new ResClient('ws://localhost:8080');
    client.get('example.mymodel').then(model => {
       console.log(model.message); // Hello, World!
       model.on('change', () => {
          console.log(model.message); // Updated to: Hello, StackOverflow!
       });
    });
    

    Considerations

    All of the solutions mentioned above (and there are more for those who seek) have with their strengths and weaknesses in areas such as:

    • Resilience - handling of lost messages and connections
    • Access control - granting access and withdrawing access to a subscription
    • Live queries - fetching partial or filtered data that is updated live
    • Offline support - working with the data while offline
    • Scaling
    • Database requirements
    • Simplicity of usage

    Just look around and see which solution suits your needs best.