From web to Electron, lessons learned

From web to Electron, lessons learned

I’ve been developing and maintaining an online ecommerce solution for restaurants and snackbars for around 10 years.

Around 4 years ago, we started the development of our first-party point-of-sales app.

We started out with a web-based version that slowly evolved to an installable Windows application, and later into an iPad app.

The web-based version was a single-page-app that ran in the browser. From a development perspective, this made the most sense, since our entire platform was web-based.

It ran on the same back-end as our ecommerce solution and used the same admin panel and database, so product entry didn’t have to happen twice and everything was centralised.

Webshop & POS ran on the same backend

For our merchants however, this was less ideal because it required an active and stable internet connection.

Whenever the merchant placed an order on the POS, it was immediately sent to our backend system and the interface waited for confirmation before giving a signal to the printer.

While this setup seemed efficient, it quickly revealed 2 significant drawbacks:

  1. Our merchants are not the most tech-savvy people, so they often buy the cheapest internet subscription available, usually from a lower-tier ISP. This means that download and upload speeds are not the best in class.
  2. At the time, our backend server wrote the orders immediately to the database before responding to the request. This same backend and database was used for our online ordering system, which meant that during peak hours, response time would increase, as the database was a shared resource.

Both of these reasons contributed to the feedback we were hearing all around: The POS system felt slow, impacting their operational efficiency and, ultimately, customer satisfaction. And it made sense, because field surveys showed some merchants had to wait for over 5 seconds before a receipt would be printed - not acceptable.

Shift to Electron: Improve performance and reliability

To address these challenges, we pivoted towards developing an Electron-based POS app. This decision was driven by two main goals:

  • Our POS system needs to be available without an active internet connection and even when our back-end experiences high load or even an outage
  • The application should feel snappy, and more importantly, it should be reliable and consistent

Our first version of the Electron-based app was mainly a copy of the single-page-app, with a swapped out backend. Since Electron is node-based, we could create our own local backend that would mimic the online backend.

POS with a swapped out backend

We used Express for developing our HTTP server, and Prisma for interacting with a local SQLite database. In hindsight, shipping our app with Prisma included was not the best idea, but more on that another time.

To manage the POS, we built a small local admin interface that could manage products, prices and settings.

And there we have it - the MVP for our Electron-based POS was ready to be shipped. This app worked 100% offline:

  • we had an offline database
  • we had an offline backend
  • we had an offline admin panel

The initial feedback was overwhelmingly positive, so that confirmed we were on the right path and we doubled down on our Electron development, adding features like payment terminals, USB peripherals, automatic updates and more.

One of the big negatives however, was that the admin interface of the point-of-sales was clunky and cumbersome to use:

  • Our POS systems were touch-screen devices and rarely had a keyboard and mouse
  • Whenever our support team had to step in, it had to happen through Teamviewer, impacting the service
  • Usually our merchants already had a webshop with us, so they had to maintain their menu twice (once for the webshop, and once for the POS, since it was offline)

Finding middle ground

So by now, we had made the shift from a fully online system, to a fully offline system, and we thought to ourselves: We need to find some middle ground and find a way to get the best out of both worlds.

Finding the sweet spot between online & offline functionality

We slowly started introducing features that required an active internet connection, but at the same time made sure the POS could perfectly work without them.

One of the big updates we did, was to remove the local administration panel, and make the POS configurable from our cloud-based admin panel.

When the POS starts up, it downloads the configuration and keeps a local copy. The POS then does its best to keep in sync with the latest changes, but if it fails to do so, it will continue working.

POS downloads a configuration JSON file, and stores a copy

This change allowed our merchants and our support team to manage the POS from wherever they wanted, and it didn’t impact the service.

And finally we made sure to also upload the local order history in the background, so we could make our reporting accessible through the cloud interface.

To achieve this, we created a ‘sync worker’ that would batch a group of orders and send them to our cloud back-end, when possible. If there was no internet connection, or the back-end system was down, the sync worker would simply try again at a later time, until it succeeds.

Sync worker syncs a batch of local orders to the cloud, when possible

Final words

And there we have it, it’s been quite a journey and I wanted to leave you with these 2 final pieces of advice:

  1. Never assume anyone has a stable internet connection. Prepare for less ideal network conditions and make sure even those users without a stable connection are not becoming too frustrated with your service.
  2. Always try to find some middle ground. When we launched our first POS version, we went all-in on online features. When we launched our first Electron app, we went all in on offline features. In hindsight, this was not ideal and we had better spent some time finding the middle ground in either system, instead of changing course so drastically.

Thanks for sticking with me, I hope you learned a thing or two, and I’ll see you in the next one!

Subscribe to sabatino.dev

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe