Bellesoft IPTV

Case study · Bellesoft IPTV

A property-wide app update went from six months to a single publish

In-room entertainment runs on set-top boxes behind locked doors. Updating them used to mean waiting for each room to empty and sending someone in. This backend hosts the application and the boxes fetch it themselves, alongside the channel index, promotional media and the settings that differ from one room to the next.

Snapshot

ClientHospitality software vendor, in-room entertainment for hotels
Deployed1 hotel, 500 rooms
BuiltChannel index, promotional media, per-room configuration, application distribution
StackLaravel, Filament, PHP, MySQL, Redis, Docker
TimelineMarch 2026 to present
My roleBackend. The Android TV application was built by a frontend developer.
Rolling out an app update6 months, room by room. Now one publish.

The Challenge

The televisions are fixed, identical and unattended. The person configuring them is a hotel IT administrator, not a developer. What plays in a room depends on which room it is. Two problems follow, and the first one dominates.

  • A release was a six-month operation. Every box had to be updated by hand, and a room can only be entered when it is vacant. That turns a software release into an occupancy-scheduling problem: someone has to track which rooms are free, plan the sequence, and work through 500 of them as they empty. Six months from first room to last, during which the property is running two versions.
  • Settings are per room but administered per property. An administrator sets a property-wide default and then needs a handful of rooms to differ. Modelling that as either a single global setting or a per-room record alone gets it wrong in both directions.

If you ship software to hardware you cannot reach remotely, the first problem is yours too, and it gets worse with every device you add.

The Approach

The backend is the update channel. Application packages are records with version metadata and a download endpoint. The box asks whether it is current instead of waiting to be visited, so a release is published once and propagates on its own.

That is the whole six months. The engineering is unremarkable, which is the point: the cost was never technical difficulty, it was that nobody had made the boxes able to ask.

The trade is that the service now serves large binaries over hotel networks, which gives it a bandwidth profile nothing like an administration API and forced its upload limits up accordingly.

A property-wide default with per-room overrides. Configuration resolves before the television is told anything, so the client consumes one answer and never knows which layer produced it. Set the property once, override the suites.

Room state is read from a cache, not fetched live. Occupancy syncs from the property management system and is attached to requests with a short expiry. This trades freshness for independence deliberately: in-room entertainment stays up when the front desk system is busy. The window is thirty seconds, widened from five because the tighter value produced churn without improving anything an operator could observe.

An off-the-shelf admin, on purpose. The audience is a handful of hotel IT staff doing CRUD on a few hundred records. A bespoke administration application would have cost more than the backend it administers and needed maintaining for the life of the product. The constraint is that several actions are more awkward than a purpose-built form would be.

The backend indexes streams, it does not carry them. Channels are entries pointing at m3u8 playlists broadcast by a separate service on the property's private network. This system never touches video. Keeping delivery out of it is why one developer could hold the rest.

The Build

A general solution built and deleted in a day. Room-scoped settings were first modelled as a generic mechanism that could attach configuration to any entity type. It supported target types that did not exist and made resolution harder to reason about than the one case actually required. Replaced the next day with something that does one thing.

I would rather record that than not. The general version was written first, and it was worse. If a requirement ever needs settings scoped to a floor or a room type, it gets generalised then, against a real second case.

Compression shipped inside the request, then moved out of it. Uploaded media was compressed during upload, making upload time proportional to file size on a hotel network. A week later it moved to a background queue, with a command to backfill everything already stored. Media is briefly available unoptimised, which is the trade.

Results

BeforeAfter
Rolling out an app update6 months, room by room, as rooms emptiedOne publish
Versions running at onceTwo, for monthsOne
Changing the channel lineupDeveloper or vendorHotel IT staff, in the admin
Rooms differing from the defaultNot supportedPer-room overrides
Entertainment when the front desk system is busyCoupledIndependent, 30 second window

Concurrent client load and stream performance were not instrumented, and no figure is given for either. The six-month figure is the client's account of the previous process.

Next

If updating software in the field means sending someone to it, that is a distribution problem with a known fix. Get in touch.

08 · Contact

Let's Build Something Useful

If you're looking for someone to develop business software, improve operational processes, or integrate existing systems, I'd be happy to discuss your project.