Multi-tenant cloud platform / Production
SpeedFlowLink
Cloud platform for managing fuel dispensing stations — a Blazor front end, several APIs with separate responsibilities, and a shared multi-tenant data model.
The problem
A dispensing station combines physical devices, floor operators, self-service, billing and third-party systems. Each speaks a different protocol and has its own life cycle: devices get replaced, operations cannot stop, and one customer's data must never reach another. A single monolithic service would have tied the hardware release cadence to the web interface's.
Constraints
- Strict per-customer isolation on a shared database
- Field devices cannot be updated at the same pace as the cloud
- 24/7 operation — the schema evolves without long maintenance windows
- Surfaces with opposing requirements — the web tolerates latency, hardware does not
Decisions
Outcome
- Blazor Server front end consuming the APIs through injected HTTP services, with logic in ViewModels and thin views
- Data model with per-area prefix conventions — parameters, administration, general, customers and security — that makes the schema readable without opening documentation
- Real-time device status pushed to the interface over a messaging hub
- Third-party integration channel isolated from the business core
How the system is split
The solution is not one large service but a set of services grouped by who they talk to, over a common database:
- Core business API — serves the web interface and holds the domain logic, entities and schema evolution.
- Device API — the channel to hardware devices, with direct control over them.
- SoftAPI — a self-contained service for software-based device communication. It shares the database but deploys on its own.
- Integrations API — the entry point for third-party systems, isolated from the core.
- Real-time hub — pushes device status to the interface so the browser never has to poll.
- Self-service — the surface for unattended operation.
That split is the product’s structural decision: it lets the device channel — the one that cannot fail — evolve at a different pace from the web interface.
Multi-tenancy as an invariant, not a convention
Every customer shares the database. Isolation is solved at the data layer: the repository receives the authenticated user’s context and applies the owner filter uniformly. No query decides on its own whether to filter.
It is the kind of rule that, left to each developer’s judgement, works right up until someone writes a new query in a hurry.
What I worked on
Integrations, backend, front end and data model. That means writing endpoints and domain services, building Blazor screens with their ViewModel, designing and evolving tables, and — what taught me most — keeping all three consistent when a business change cuts across them.
The full path, not just implementation: gathering the requirement with whoever raised it, designing the solution, building it, testing, continuous integration and seeing the release through.
Why it belongs here
It is the system I have spent the longest with, and where decisions have consequences measurable in years. It shows sustained work on a real product: not an architecture drawn on a whiteboard, but one that survived five years of changing requirements.
The source code belongs to Speed Solutions. This case study describes architecture and decisions only — no source code, customer data or business figures.