Client work · 2016–now · for Mogul Wireless

Mogul Wireless

When a reading goes wrong, someone hears about it.

Mogul watches over the vaccine fridges, freezers and rooms of hospitals, pharmacies and labs. We started maintaining and building on its web app in 2016, and ten years on, I still do, every month.

Client
Mogul Wireless
We look after
Rails Web App
With
Ruby on Rails, PostgreSQL, Sidekiq, Sinatra, Twilio, Heroku
A day's report for a demo group of vaccine fridges in Mogul's web app: a freezer and two refrigerators charted against their allowed range, one spiking out of it in the afternoon.

The brief

Monitoring for healthcare

Mogul watches the temperature, humidity and room pressure in hospitals, pharmacies, laboratories and cancer treatment centres, and gets hold of someone the moment a reading goes wrong. Its web app is where all of that is set up, alerted on and reported.

The challenge

Looking for a partner

The app had been built around 2012 by another firm, and it was running without major issues, but there were performance problems to look at, a lot of functionality Rob Bell, Mogul's owner, wanted to add, and no software firm he was happy working with.

What we made

Ten years, and counting

A monthly retainer, from March 2016, to look after the app and keep building on it: the servers, the performance, every framework upgrade, and a steady run of new features. A team of us did that until 2020, and I've done it since.

Illustration of a medical fridge reading 43 degrees with an alert sign, sending a wireless signal to a gateway and the cloud

2016

Taking It Over

Mogul didn’t start with us. Early in my career I’d worked as a consultant at another firm, and one of its owners had built this product for Mogul, going back to around 2012. By 2016 they were no longer interested in looking after it, and Rob Bell, Mogul’s owner, had struggled to find a firm to work with that he was happy with.

So we took it over. The app was running without major issues, but there were performance problems to look at, and Rob had a lot of functionality he wanted to add. More than anything, he was looking for a partner to move forward with. We signed our agreement in February 2016, my first commit was on the 23rd, a small one adding notes to a sensor, and the retainer began on 1 March.

An alert tree for a group of vaccine fridges, on demo data: five people, each with a delay of 0, 15 or 30 minutes, ticks for email and text, and a phone call for two of them, above the tree’s membership history of who added each of them and when.

What it does

Watching Every Five Minutes

Wireless sensors sit in the fridges, freezers and rooms that matter, and read the temperature, the humidity or the room’s pressure about every five minutes. A gateway on site collects their readings and sends them on to the collector, a small app of Mogul’s own, which queues them for the web app to import.

The web app is where everything else happens. Each hospital or pharmacy is organised into groups, each group has its sensors and their limits, and each has an alert tree: who hears about a problem, by text, phone call or email, and how long after it starts. Everything is recorded, because an auditor will want to see it.

Today that’s about 2,500 sensors on 91 gateways, sending in something like 950,000 readings a day. The app has raised more than 450,000 alerts since 2012, and sent 1.68 million notifications about them.

A day’s report for a group of vaccine fridges, on demo data: a freezer and two refrigerators, each charted over 24 hours against the green band of its allowed range, with refrigerator B spiking red above it in the early afternoon and back to 39.1°F now.

The hard part

When the Gateways Come Back

Some of the hardest moments over the years have come from a gateway doing exactly what it should. When one has been offline and comes back, it sends the collector everything it has been holding, all at once. When enough of them come back together, the collector is flooded with readings, all of which still have to be imported, checked and charted.

So we made it scale. In 2017 we moved the app and its collector to Heroku, with Sidekiq behind them, and protected our services so a flood of readings wouldn’t take them down. In late 2018 we took the import apart. A gateway’s log is now parsed into its readings, each reading is imported as its own job, in parallel, and only once the last one lands are the aggregates and the displays brought up to date, once per import instead of once per reading.

A sensor display for a blood bank refrigerator, on demo data, gone amber because it’s out of range: 7.3°C in large type, its range of 1.1°C to 6.1°C under it, the day’s low and high across the top, a red Reset button and the Mogul logo.

2018

Readable From Across the Room

Not everyone who needs to know a fridge is warm is logged in. In 2018 we built the sensor displays: small, independent screens that sit beside the sensors, each showing a rendering of its readings that’s meant to be read from across the room.

They’re served by the web app, can be embedded anywhere, and have been tuned over the years for the small browsers they run in, including a stylesheet all of its own for one of them. In 2019 we darkened their colours for contrast, and this year I raised it again, with WCAG’s contrast guidance in mind. Rob is installing more and more of them.

The same kind of display for a vaccine refrigerator in range, on demo data: 4.2°C in large green type on Mogul’s dark teal, with its range of 2.2°C to 7.8°C and the day’s low and high. A display for a pharmacy storeroom’s sensor, on demo data, reading two things side by side on the same dark teal: 21.0°C and 40.7% humidity, each with its range.
A new Vaccines for Children verification for vaccine refrigerator B, on demo data: its current temperature of 39.1°F, the 24 hours’ recorded range of 38.0°F to 40.9°F, the acceptable range of 36.0°F to 46.0°F, a date and a box for notes.

Compliance

The Reports Auditors Ask For

A lot of what Mogul sells is peace of mind at inspection time, so over the years we’ve kept rolling out new kinds of sensors and more of the compliance reporting its customers need: door sensors in 2020, compliance reports in 2022, and daily and monthly reports sent on a schedule.

In early 2025 I built support for Vaccines for Children, the federal programme with its own rules for checking and recording vaccine fridges. A sensor can be enrolled, someone performing a check sees the lowest and highest temperatures of the last 24 hours, reminders go out twice a day until the checks are done, and the whole record comes out as a PDF.

Alert Delivery for a demo hospital: 3 people will not get their alert texts, 5 can be texted right now, 1 is waiting to be confirmed and 1 opted out, a coverage bar in the same colours, and a table of who isn’t getting their texts and why: opted out, unreachable, or a code sent and never entered.

2026

An Alert You Can Trust

An alert is only as good as the phone it reaches, and a wrong or dead number means somebody stops getting alerts and nobody finds out. This year’s biggest piece of work, and the one I’m proudest of, was closing that gap, with much deeper auditing and a much closer integration with Twilio.

Everyone now has their own record of their own number, and it isn’t relied on for alerts until a code texted to it comes back. Twilio’s word on every message is recorded against the number. A STOP or a landline is written off at once, a phone that’s just switched off has to fail ten times in a month before it is, and a failure that’s really about us, not the phone, never writes anyone off, because acting on it would silence everyone at once. When a number stops working, its owner is emailed to say so.

A client’s admin can see who won’t get their alert texts, and why, and a chart of delivery errors over the last thirty days. And the phone calls got better too: alerts are read in a neural voice, and door alerts finally have something to say on the phone.

A phone number that has been written off, on demo data: marked Unreachable, with the ten delivery failures reported for it over September, seven because the handset was off or out of reach and the last three because the carrier does not recognise the number. A resolved alert for vaccine refrigerator B, on demo data: its chart rising above the allowed range and back, who was notified by email, text and phone at 0 and 15 minutes, one text that failed, the later escalations cancelled once it was resolved, and a note of what was done about it.
Mogul’s admin, restyled in its own slate and green, showing a demo client’s details: active, whether Mogul provides its hardware support, and whether its users must sign in with a one-time code.

Keeping up

Every Upgrade, as It Comes

Looking after an app for ten years mostly means keeping it current, and the work has an ebb and flow to it. Between August 2024 and December 2025, I took it from Rails 6.1 through every version to Rails 8.1, turning on each version’s new defaults one at a time, and Ruby up to 3.4. Along the way it moved to GitHub Actions, Sidekiq 7, Active Storage and Pundit.

This summer the admin, where Mogul’s own team works, was restyled in Mogul’s own palette, and the login was made to look as professional as the product is. I’m also building Mogul’s new marketing website, which isn’t live yet.

In his words

Ten Years of Rob’s Email

Rob doesn’t write testimonials. He writes short emails, often the same day something goes live, and after ten years they say more about how this has gone than anything I could. These are his, exactly as he sent them, trimmed only where marked, with what I’d just done.

Rob Bell, Mogul Wireless

Thanks for the update! Appreciate all your work on this project.

Six months in. I’d written to say the move from the old servers to AWS was close, and that parsing humidity and battery data from the sensors was next.

Rob Bell, Mogul Wireless

Great news Matt!

A new home. The app was back online on its new servers after about 25 minutes offline.

Rob Bell, Mogul Wireless

You’re my hero – thank you for your help with this!!

A gateway with the wrong clock. It had stamped weeks of readings with the wrong year, so I re-imported them, and the charts and reports had their data back.

Rob Bell, Mogul Wireless

That looks great!! Simple to manage.

A first design for scheduling alert trees by the time of day.

Rob Bell, Mogul Wireless

You don't know how happy I am right now!! Thank you so much!

The same day. New ultracold freezers for COVID vaccines needed a bigger correction on their sensors than the app allowed, and Rob’s customers were relying on Mogul for the proof of temperature they needed before they could receive vaccine. It was live that day.

Rob Bell, Mogul Wireless

Excellent - thanks Matt! Funny that we haven’t run into this earlier😀

A years-old bug. Alert trees scheduled for Sundays were being skipped, so I fixed it and added tests.

Rob Bell, Mogul Wireless

Really appreciate your efforts getting this written.

Compliance reporting, on staging for Rob to try before it went live that November.

Rob Bell, Mogul Wireless

Wow - this is unbelievable!

Thank you for your help on this Matt.

Texts stopped arriving. A stalled carrier registration was keeping alert texts from getting through, so that evening I set up a toll-free number to send them from.

Rob Bell, Mogul Wireless

Thanks Matt! This is going to be a huge help to our clients!

Help videos, a library Mogul’s admins manage and every client sees under a new Help menu.

Rob Bell, Mogul Wireless

Thanks for the update. We appreciate having you on our team so much!

Back from a month away, and picking up where I’d left off.

Rob Bell, Mogul Wireless

Beautiful - well done Matt!!

A database upgrade with twelve minutes offline. The readings that queued up in the meantime were all imported about three minutes later.

Rob Bell, Mogul Wireless

This is perfect!

Thank you so much!!

Reports from the archive. A client needed its reports going back to 2022, so I restored the archived readings from backup to make them.

Rob Bell, Mogul Wireless

Thanks Matt - best service ever!

Fixed the same day: two problems a client’s admin had run into after the latest upgrade.

Rob Bell, Mogul Wireless

I would say we have contracted your firm for the past 15 years to lead our web based software development team. … You bring knowledge and technical expertise that is super valuable to our company.

Before a call with one of Mogul’s customers about a security questionnaire, I’d asked Rob how he wanted me to introduce myself.

Rob Bell, Mogul Wireless

That’s fantastic Matt! Just tested it - worked great!

A second step at login, a one-time code, switched on for Mogul’s admins, and ready for any client that wants it.

Rob Bell, Mogul Wireless

I am installing more and more of these, so having their performance improved is super beneficial!

The sensor displays now ride out a dropped connection, with a banner to say so, instead of reloading themselves every hour.

Rob Bell, Mogul Wireless

We are so grateful for the amazing service you provide.

Ten years in, replying to my note about the retainer for the year ahead.

Rob Bell, Mogul Wireless

Matt - this is awesome, and when we add the telephone side it will totally tighten up any opportunity for error. It’s a big deal - I’ll definitely need to send info out to the clients explaining the feature and upgrade.

Verified phone numbers, the day they went live: every number proven before alerts rely on it, and a dead one flagged, with its owner told.

The Craft

Readings, partitioned three times

Hundreds of millions of readings live in one partitioned table, split by month. It started as child tables chosen in Ruby, which wasn’t thread safe, then moved to triggers and functions in PostgreSQL, and in 2021 to PostgreSQL’s own native partitioning, with no triggers and no third-party extension. Old readings are archived, so the live tables stay quick.

Charts without gaps

Mogul wants a day’s chart in fifteen-minute averages and a month’s in four-hour lows, averages and highs, in each sensor’s own time zone, and never with a gap. It took four attempts to get the monthly reports both fast and flexible: the app now stores hourly aggregates and lets PostgreSQL build everything else from them.

Locked down

A login can require a one-time code by email, for one person or a whole client. An account locks after six failed attempts. Password reset codes sent by text are hashed, expire after fifteen minutes and allow only a few tries, and Twilio’s calls back to the app have their signatures checked.

Tested, then shipped

RSpec covers the code and Cucumber covers what people actually do, and this September I added scenarios for more of those workflows, from reviewing an alert tree to who may acknowledge an alert. A change that passes goes to production on Heroku automatically, and Dependabot keeps the dependencies moving.