M2M Platform
Case study · M2M PlatformPhase 1 · Integrating

Replacing a legacy telecom platform, one module at a time

Redesigning an enterprise connectivity platform
for 70,000+ SIMs, starting with the one module
everything else would inherit from.

Senior Product Designer · Enterprise IoT & Telecom · Web platform

Counts from my audit of the legacy system against the delivered design. Adoption and task-time metrics are pending post-launch instrumentation.

02 · The challenge

Built for a smaller,
slower world

The SIMs inside delivery trucks, payment terminals, meters and trackers. When one stops transmitting, something physical stops working. Operators had learned the legacy system’s quirks by memorising workarounds, and that competence hid the cost.

LegacySIM Overview. Twelve columns of raw identifiers, no fleet summary. Status is ALL-CAPS text in column eleven; a red or green dot means “In Session” with no legend.
LegacyAdvanced Search. 44 controls: fields, per-field operators, one global AND/OR. Powerful, and the only way to ask a non-trivial question. Operators kept a text file of working queries.

Every legacy screen on this page is a neutral wireframe recreation, redrawn to preserve the original's structure — column counts, tab counts and control counts — without reproducing the operator's branding or any real data.

No fleet-level state

The platform could show 25 rows, not your fleet. Every aggregate question meant an export to Excel.

Fleet state is the landing view

Clickable status cards above the table: reading the fleet and narrowing it become one gesture.

Purely reactive

Overages, roaming spikes and IMEI mismatches were discovered on the invoice.

Triage surfaced up front

A consistent AI insight banner names the risk, ranks it by consequence and offers one next step.

Two gears, no middle

One exact identifier, or a 44-control boolean builder. The everyday query fit neither.

A composable query bar

One bar across seven identifiers, inline filters underneath, Advanced Search one click away.

Raw data, not information

Bytes, not megabytes. Timestamps, not “6 days ago”. Secrets in plain text.

Translate, don’t transcribe

Every reading carries its quota, trend and recency. PIN/PUK masked behind an explicit reveal.

Broken edges

No way to tell “no data” from “failed to load”: a costly ambiguity in an incident.

Never render silence

Every empty, loading and failed state is designed, and every one says what to do next.

English-only, LTR-only

Arabic customer names were already in the data. The interface wasn’t built to hold them.

Arabic from the first frame

Real Arabic strings in every layout, with the RTL mirror specified alongside LTR.

Because operators had adapted, the platform’s problems read internally as training issues rather than design failures. Part of the job was making the failures visible again, with an audit of the live product rather than a competitor sweep.

03 · Strategy

Why SIM Management
went first

The brief was open: replace the platform outright, not reskin it. The risk in a brief that size is designing twelve modules shallowly instead of one properly. The first thing I argued for was sequencing.

Analytics dashboards

Inherits the KPI card, chart and empty-state library, and the persistent filter bar.

Sprint 2 · Delivered

AI layer

Insights banner, docked assistant and full-page assistant, with one behaviour model everywhere.

Sprint 3 · Delivered
In plan

Invoices & billing

Consumes the established table, drill-down and audit patterns. No new list-view inventions.

Next
In plan

Reporting, support & users

Customer and user management, reporting and support, built on the same shell and states.

Next
SIM Management

Sprint 1 · the pattern source

TableSearchBulkAuditStates

Three reasons it went first

  1. Reason 1

    It’s where the time goes

    SIM lifecycle is the highest-traffic module by a wide margin. Fixing it delivers the most relief per unit of design effort.

  2. Reason 2

    It contains every hard pattern

    Dense table, bulk destructive actions, deep drill-down, audit log, config rules, sensitive fields and search at two levels. Solve them here and later modules inherit solved problems.

  3. Reason 3

    It’s the credibility test

    If the new platform handles 70,000 SIMs convincingly, stakeholders fund the rest. If it can’t, no dashboard will save it.

  • Answer the question before it’s askedFleet state before rows. Deltas before totals. Risk before history.
  • Two gears, and a middle oneEvery powerful capability needs a low-effort entry point.
  • Translate, don’t transcribeBytes become megabytes with a quota. Timestamps become elapsed time.
  • Never render silenceEvery empty, loading and failed state says what to do next.
  • AI is infrastructureSame placement, same tone, same dismiss behaviour, everywhere.
04 · Interactive prototype

SIM Overview,
rebuilt

A working slice of Sprint 1. Click a status card, search, select rows and act on them, open a SIM. Pick a walkthrough step or explore freely.

SIMs

Demo fleet · sample data
AI insight

Sample data. Rebuilt in the browser from the delivered Figma designs; the front-end team owns the production build.

05 · Design decisions

Seven decisions that
carried the module

Each started as a specific failure in the legacy audit. The failure stays attached to the fix, because the fix on its own is just a screenshot.

Decision 015 searches → one default view

Make fleet state the landing state, and make it clickable

Problem
The legacy overview opened onto rows. Answering “how is my fleet doing?” meant an export.
Move
A status card row above the table (All, Active, Suspended, Terminated, Inactive, Ordered), each with a today-delta, each a filter on the table below.
Why
Reading fleet state and narrowing to a subset become one gesture, which is how operators already think: “213 suspended, show me those 213.”
LegacyLegacy overview. Rows first; no fleet-level summary anywhere.
RedesignSIM Overview. Fleet state, then the AI insight, then search, then rows, in descending order of how often the answer is needed.

Also in this flow

Customize viewCustomize view. Personalisation with a hard cap: six slots force a choice, so the row stays scannable. A billing analyst and a field operator don’t watch the same numbers.
Decision 0244 controls → 1 query bar

Give search a middle gear

Problem
One exact-match box, or 44 controls with boolean operators. Nothing in between for the query operators ran most.
Move
One composable bar across IMSI, MSISDN, ICCID, business unit, cost center, service profile and customer label, with four inline filters beneath and Advanced Search one click away.
Why
Progressive disclosure sized to real frequency, not feature parity. The legacy builder’s power is kept; it’s just no longer the price of admission.
LegacyLegacy. The only way to ask a compound question.
RedesignRedesign. The same question answered in the toolbar, with result count and active filters visible.
Decision 03

Make bulk operations safe before making them fast

Problem
Operators manage SIMs in the thousands. One at a time is untenable, and bulk without guardrails is worse.
Move
A contextual action bar on selection: Suspend, Change profile, Manage labels, Terminate. A persistent count, one-click Deselect all, destructive actions set apart in red.
Why
The dangerous moment isn’t the click, it’s the ambiguity before it: not knowing what “selected” means while a filter is active. The count does more safety work than the dialog.
RedesignSelection state. The bar exists only when it’s actionable, and states the selection in words. Terminate is the only red item.
Decision 048 tabs → 4

Eight tabs to four, with a header that never moves

Problem
Eight tabs organised by database table, not by task. Switching lost context about which SIM you were on.
Move
Overview (is it healthy?), Configuration (what may it do?), Diagnostics (why is it misbehaving?), Activity (what happened?), under a persistent identity header with copy on every identifier.
Why
Support agents cross tabs while a customer is on the line. The header lets them read an ICCID aloud from Diagnostics without navigating back.
LegacyLegacy. Eight tabs, flat hierarchy, secrets in plain text.
RedesignRedesign. Consumption first, identity second, recent activity third; PIN/PUK masked behind an explicit reveal.
Decision 05raw bytes → quota + trend

Translate the data instead of transcribing it

Problem
“Current Data Usage (Bytes): 1342976.” Technically accurate, operationally useless.
Move
1.5 MB with a bar reading 1.5 / 10 MB and “last session 6 days ago”. Rules read as sentences: “When IMEI mismatch → Then suspend SIM.”
Why
A number is only information once it carries its own comparison. Quota, trend and recency turn a reading into a decision.
LegacyLegacy. The entire Usage Information tab.
RedesignSIM Details · Overview. 1.5 MB against a 10 MB quota bar, SMS against its plan, sessions with a trend, and the last session as elapsed time.

Also in this flow

ConfigurationConfiguration. Rules as sentences with Editable and Active badges; add-ons carry “Expiring soon” rather than a raw date.
Decision 063 terminal states designed

Design the edges: empty, loading, failed

Problem
“No element selected/no data found” under a full table header. No way to tell a real zero from a failed fetch.
Move
Every terminal state is a designed component. No-results echoes the query and offers Advanced Search. Failure keeps the SIM’s identity header intact behind an inline error.
Why
With the header alive when the body fails, an operator can still copy the MSISDN into a ticket. The interface degrades into something useful, not a dead end.
LegacyLegacy. An error and an empty state at once.
RedesignNo results. Echoes the query, explains partial matching, offers the next move.

Also in this flow

Load failureLoad failure. The content is gone; identity and the escalation path are not.
Decision 07+ Origin · Manual / API / File

Make the audit log answer “who and how”, not just “what”

Problem
Changes arrive from people, API integrations and bulk file uploads at once. A log without provenance is close to useless in an incident.
Move
Origin (Manual, API, File) as a first-class, filterable column with its own icon, alongside status, type and date bounds. Recent activity previewed on the Overview tab.
Why
“Who changed this profile?” and “did our integration do this?” have different remediations. Origin is the cheapest way to separate them.
ActivityActivity. Transaction search, four filter dimensions, Origin with an icon per source.
DiagnosticsDiagnostics. IMEI match, last IP and eNodeB, raw CDRs, and the fingerprint block regulated customers need for SIM-to-device binding.
06 · Sprint 2 · Dashboards

Every metric has
one owner

The dashboards weren’t under-designed, they were over-supplied: the same numbers in slightly different cuts across tabs, with no agreement on which was authoritative.

Finding 01

The same metric, four times

Business-unit cost on four tabs. Two widgets that were one query under two names.

Finding 02

Charts as blank axes

Grids and labels, then nothing. The legacy silence, inherited into a new product.

Finding 03

The signal was buried

A large “Unknown” slice dominated the status donut while Active barely registered.

Finding 04

Zero read as zero

“$0.00” looked the same whether it was real or a failed fetch.

A dashboard that shows the same number four ways doesn’t give you four insights. It gives you four chances to disagree with yourself. Two of the findings turned out to be data failures wearing a design costume; telling them apart quickly is most of a dashboard review.

Bundle Details was the clearest case. It always opened empty, which read as a broken empty state — the cause was a default filter set to “Consumed: 80%+” against a fleet sitting at 1–2%. I changed the default to “Any” and routed the underlying issue to the API owner, rather than redesigning a component that was working correctly.

07 · Sprint 3 · AI layer

AI that triages,
not decides

The instruction was “add AI”. The design problem was what AI may do in a system where a wrong bulk action cuts connectivity to a customer’s field equipment.

01

Grounded and scoped

Every answer cites live platform data and is limited to what the signed-in user can already see. Source chips and a sync time sit under each response.

02

Ranked by consequence

Not “47 SIMs are near their limit” but “12 will overage; here are the top 3 by projected cost.” Triage is the product.

03

It prepares, you approve

The assistant can draft a bulk suspend. It can’t run one. Every action lands in the normal confirmation flow, with a human as the last step.

RedesignAssistant in context. Docked beside SIM Overview with visible scope chips. It leads with the consequence, shows its working, cites sources and ends in actions the operator takes.
RedesignFull page. The same component on its own route for longer investigations. Suggested prompts are the four questions operators actually ask.

The insights banner appears verbatim on SIM Overview, Details, Configuration and Diagnostics. That consistency isn’t tidiness: if AI is a banner in one module and a modal interrupt in the next, users stop trusting it, and an untrusted assistant is worse than none.

08 · The system

Built once,
used everywhere

I built on the client’s existing design system, using its tokens and variables, and added the few components the new cases needed. Sprints 2 and 3 consumed them straight away.

  • #008C88Brand primary
  • #E6F4F3Primary light
  • #DD3356Destructive
  • #10B981Success
  • #1D252DText primary
  • #8E9AA0Text muted
  • #F9F9F9Card surface
  • #F8FAFCTable header

Type scale: 18 / 16 / 14 / 13 / 11 / 10 px from page title to timestamp. Spacing on a 4–6–8–12–16–20 scale, 8px radius for buttons and cards. Display sizes are reserved for hero numbers, so density is never traded for scale.

New component

Clickable KPI card

Status dot, label, number, today-delta. It doubles as a filter on whatever sits beneath it.

New component

AI insights banner

Fixed anatomy, fixed placement, session-scoped dismissal. Identical on five surfaces.

States

Edges, designed

Empty, loading and failed each get their own component. Switch between them.

  • Data tableStatus dot, copy icons on identifiers, icon actions column, sticky selection bar.
  • ToolbarSort, sync time, export. Freshness lives here, not on KPI cards, so it’s never mistaken for a real zero.
  • Filter barBusiness unit and bill cycle, persisted across dashboard tabs so a scoped question survives navigation.

Arabic and RTL, from the first frame

I designed with real Arabic customer names in place rather than Latin placeholders, and specified the RTL mirror for sidebar, filter bar and label alignment alongside LTR. Retrofitting RTL after a table system is built is a rewrite; specifying it during is a constraint.

شركة الواحة الزرقاء للنقل A fictional Arabic customer name, used to test RTL rendering
09 · Outcome

Where it
landed

Three sprints designed and handed over in Q2 2026. Phase 1 is semi-live, awaiting final integrations. Reported here: delivered scope and audit counts, not production metrics.

−50%

Detail tabs

SIM Details went from eight tabs organised by database table to four organised by task.

9→4

Bundle lookup

Checking a bundle’s status went from nine steps across two nested search forms to four.

44→1

Search

A 44-control advanced search replaced, for everyday queries, by one composable bar plus clickable status filters.

Delivered in three sprints

  1. Sprint 1

    SIM Management

    Overview, four-tab Details, Configuration, Diagnostics, Activity, plus loading, empty, no-result, error and collapsed-nav states. The module the rest inherits from.

  2. Sprint 2

    Dashboards

    Overview, Customers, Cost, Usage & Bundle Health, Bundle Details and Tickets, re-cut so each metric has one owner and data gaps are surfaced as KPIs.

  3. Sprint 3

    AI layer

    Insights banner, docked and full-page assistant, conversation history: one behaviour model applied on every surface.

10 · Carry forward

What I’d carry
forward

Two things I now set up in week one of any platform rebuild.

  1. 01

    Lock the IA before the pixels

    On a platform this deep, navigation groupings drift as modules grow. A week-one card sort and one stakeholder decision cost far less than reconciling structures mid-build.

  2. 02

    Set the measurement plan at kickoff

    Capture task-time and export-frequency baselines on the legacy system while it’s still live. That window closes when the replacement ships, and it’s why this page reports audit counts rather than production metrics.

Thankyou

Let’s untangle something
complex

Dense operational platforms, legacy migrations and the teams behind them. That’s the work I like most.