Case study · Telecommunications
A hundred and sixty characters, no headers, and a sender who is lying about who they are.
A detection engine for SMS traffic: content classification, campaign linking and resistance to the obfuscation that defeats keyword filters, exposed through an API and an analytical query layer, with a labelling pipeline that turns analyst decisions into the next version of the models. Delivered 2025–2026. The client is under NDA, so this page publishes the system rather than the customer.
- Delivered
- 2025–26
- Client
- under NDA
- What we built
- detection engine classification + campaign linking
- Signal types
- 3 content, behaviour, routing
- Measured, our bench
- 4.1–4.3× Bayesian kernel, GPU vs CPU
- Not claimed
- an SS7 firewall
Why there are no detection rates on this page
They exist. They were measured on the client’s traffic, and they are covered by the same agreement as the client’s name. Publishing somebody else’s operational figures to win our own work is not a trade we are willing to make, and a supplier who does it to one customer will do it to you. What we can publish is the engineering, the architecture, and one benchmark we ran on our own hardware — which is below, with the list of everything it does not measure.
Why SMS is the hard end of message filtering
An email arrives with headers, authentication results, a domain with a reputation and usually a few hundred words of text. A classifier has something to work with. An SMS arrives with roughly a hundred and sixty characters, a sender string that can be forged outright, and nothing else. The signal that a spam filter normally leans on simply is not there.
So the interesting information is not inside any single message. It is in the relationship between messages — the same shortened link under four different sender names, the same template with one word changed, the same recipients hit by three senders in an hour — and in how a sender’s behaviour today compares with its own behaviour last Tuesday. A system that scores messages independently will catch the first wave of a campaign and miss every wave after it.
There is also a cost asymmetry that shapes every design decision. A missed fraudulent message harms one subscriber. A wrongly blocked one-time password locks a customer out of their bank, and they will not blame their bank. Service traffic needs its own policy and its own exceptions from the first day, not as a remediation after the first complaint.
Delivered
Four pieces, and the one that makes the other three improve
This is the work that was completed and handed over, not a roadmap. Each piece is useful on its own; together they close a loop, which is the part that matters.
- 01Classification — message content scored against known patterns, with the reason for the score available rather than hidden inside the model
- 02Normalisation — mixed scripts, lookalike characters, inserted spacing and transliteration collapsed to a canonical form before anything is compared
- 03Campaign linking — individual messages grouped by shared templates, links, recipient sets and sending infrastructure, so a campaign is one object instead of ten thousand
- 04API and analytical queries — the result queryable by the operations team directly, not only through a dashboard somebody has to maintain
And underneath all four, the piece that is boring to describe and decisive in production: a labelling pipeline. Every decision an analyst makes — this was fraud, this was a false positive, this template is legitimate marketing — becomes labelled data, and the labelled data becomes the next version of the models. Without it a detection system is at its best on the day it ships and worse every month afterwards, because the senders keep adapting and the system does not.
Normalise first, then match — the difference is the fifth wave
The instinct when a filter starts missing things is to add rules. The sender swaps a letter for a lookalike from another alphabet, so you add the lookalike. They insert a full stop mid-word, so you add that too. Six months later the rule set is unmaintainable and still one step behind, because generating variants is cheap for the sender and expensive for you.
Collapsing text to a canonical form before comparison inverts that economy. Mixed scripts, visually confusable characters, inserted punctuation and whitespace, transliteration between writing systems — all of it reduces to the same representation, so a thousand generated variants become one thing to recognise. The engine then looks for variants of a known campaign rather than exact repeats.
This is also where multilingual traffic stops being a separate problem and becomes the same problem. A network carrying more than one language, with subscribers who switch script mid-sentence and type their own language in Latin characters, breaks naive filtering immediately — and is handled by the same normalisation layer that handles deliberate evasion.
Where this is going
Asking “has this sender changed” instead of “does this message look bad”
The delivered engine scores content and groups campaigns. The research line we are developing on top of it models each sender’s own normal behaviour and detects the point at which it changes — which catches a legitimate sender identity that has been taken over just as readily as a newly registered fraudulent one. This part is development, not a shipped deliverable, and it is marked as such deliberately.
The method is Bayesian online change-point detection. Each sender carries a distribution over how long its current behavioural regime has lasted; every new batch of traffic updates that distribution; a sharp shift in it is the signal. The attraction for this problem is that it produces a probability with the evidence attached rather than a threshold crossing, so an analyst can see why a sender was flagged — and so that the obvious objection can be answered honestly: a temporal anomaly is not a confirmed fraud, and the system is designed to present it as a reason to look.
What we measured, and what we did not
Keeping a model current for every sender on a network is an arithmetic problem before it is a modelling one, so we benchmarked the hot path: the posterior update, batched across 10,000 series at once.
64 hypotheses / series
- CPU 16.73 ms
- GPU 3.90 ms
- 4.3× faster
256 hypotheses / series
- CPU 68.02 ms
- GPU 16.44 ms
- 4.1× faster
Conditions
- Median of batch updates
- float32, GPU synchronised
- Single-threaded CPU baseline
- September 2026
Hardware
- Apple M5, PyTorch 2.14
- A developer machine
- Not a datacentre GPU
- Not CUDA
What this number is not
It measures one kernel — the change-point posterior update — and nothing else. Protocol decoding, tail-risk estimation, campaign correlation and any action taken on the network are outside the measurement. It is a local numerical test on a laptop class machine, not a benchmark of a full detection pipeline and not comparable to a vendor’s throughput figure for an inline firewall.
We publish it anyway, with all of that attached, because it is the number we actually have. A single measured ratio with its methodology written down is worth more than a page of throughput claims nobody can reproduce.
Under it
Message content never leaves the network it arrived in
This is the architectural line we design to, and it is not a feature — it is the constraint that decides whether a system like this is deployable at all. Message bodies, model state and the decision log stay inside the operator’s perimeter. What crosses the boundary is a short list of aggregated counters: which installation, which version, whether it is healthy, how much volume for billing.
The alternative — streaming subscriber messages to a vendor’s cloud for scoring — is simpler to build and nearly impossible to defend. It will not survive a data-protection review in most jurisdictions, and in regulated telecoms procurement it usually does not survive the first questionnaire. Designing for local inference from the start costs engineering effort once; retrofitting it costs the contract.
Detection
- Content classification
- Streaming features
- Campaign correlation
- Bayesian profiling (in development)
Data
- Stays in the operator network
- Role-based access
- Decision log and audit trail
- Agreed retention windows
Interfaces
- API for operations
- Analytical queries
- Integration with an existing gateway
- No inline component assumed
Leaves the perimeter
- Installation health
- Version
- Aggregated volume
- No message content
The team — 10 people
- 1project manager
- 1system analyst
- 1UI/UX designer
- 3ML, data and trading analysts
- 1QA engineer
- 1DevOps engineer
- 1back-end developer
- 1front-end developer
Three analysts against two developers. Detection work is not won by writing more code — it is won by the people who can tell a fraud campaign from a marketing campaign, and who keep being right about it after the fraudsters adapt.
What we would insist on earlier next time
Agree the policy for one-time passwords and service traffic before the first model is trained, not after the first complaint. These messages are the ones a subscriber notices immediately when they do not arrive, and they are structurally similar to the bulk traffic you are trying to suppress. They need their own path through the system from day one.
Build the labelling pipeline in the first month rather than the sixth. It feels like infrastructure you can defer, and it is the only reason the system is better in its second year than in its first. Every month without it is a month of analyst decisions thrown away.
And settle what the system is allowed to do before perfecting what it can see. Detection quality is an engineering problem with a known shape; the authority to act on a detection is an organisational one, and it takes longer. A system that sees everything and may do nothing is a reporting tool nobody asked for.
Questions
SMS threat detection, answered directly
What did Far Rainbow actually build here?
A detection engine for SMS traffic: it classifies message content, links individual messages into campaigns, survives the obfuscation senders use to evade filters, and exposes the result through an API and analytical queries that an operations team can query directly. Around it sits a labelling pipeline, so that decisions made by human analysts become training data for the next version of the models. It was delivered between 2025 and 2026.
Why is the client not named?
The engagement is under a non-disclosure agreement that covers both the customer and the traffic. We can describe the system we built and the engineering decisions behind it. We cannot say whose traffic it runs on, in which market, or what it found there. Under NDA, in a meeting, we can go considerably further.
Why are there no detection-rate figures on this page?
Because the ones we have belong to the client. Detection rates, false-positive rates and traffic volumes are measured on their traffic and are covered by the same agreement as their name. We would rather publish one number we measured on our own hardware, with its full methodology, than three impressive-sounding percentages nobody can check.
Is this an SS7 firewall?
No, and we do not claim one. A signalling firewall sits inline on the network path and makes protocol-level decisions; building one from scratch is a different project with different risk. What we built is the detection and classification layer. Where an operator already runs a signalling gateway, we integrate with its API; where none exists, the network component is scoped as its own piece of work rather than quietly assumed.
What makes SMS harder to classify than email?
Length and the absence of structure. An email carries headers, authentication results, a reputation history and usually enough text for a classifier to work with. An SMS gives you roughly a hundred and sixty characters, a sender string that can be forged, and no headers worth the name. Almost all of the usable signal is in how a sender behaves over time and in how a message resembles other messages, which is why campaign linking and behavioural profiling carry more weight here than content classification alone.
How do you handle deliberately obfuscated text?
By normalising before matching rather than matching harder. Mixed scripts, lookalike characters, inserted spacing and punctuation, transliteration between writing systems — all of it collapses to a canonical form first, and the comparison happens there. The engine then searches for variants of a known campaign rather than for exact repeats, which is the difference between catching the first wave and catching the fifth.
What is a Bayesian sender profile, in plain terms?
A model of what normal looks like for one particular sender — at this hour, on this day of the week, at this volume, with this mix of recipients — and a probability that what it is doing right now departs from it. It answers “has this sender changed” rather than “does this message look bad”, which catches a legitimate sender ID that has been taken over as readily as a new fraudulent one. A departure from normal is a reason to look, not a verdict: an anomaly is not proof of fraud, and the system is built to say so.
Why does any of this need a GPU?
Because the useful unit of work is one model per sender, kept current, and a network has a great many senders. Scoring them one at a time on a CPU is the bottleneck; the same arithmetic batched across thousands of profiles is what a GPU is for. Our own measurement of that kernel is on this page, with the caveats that belong to it.
Where does the message content live?
Inside the operator’s own perimeter. That is the architectural principle we design to: message content, model state and the decision log stay in the network they came from, and the only thing that crosses the boundary is aggregated counters — installation health, version, volume for billing. A design that ships message bodies to a vendor’s cloud is a design that will not survive a regulator’s question, and in several jurisdictions it will not survive procurement either.
Can this run on our traffic?
That is a question with a real answer rather than a sales one, and it depends on the integration point. The detection layer is portable; what varies is whether your platform can execute the action you want — observe, rate-limit, hold, reject — and whether the events reach us with enough context to be worth scoring. The honest first step is a short technical session about your interfaces, not a proposal document.
Next
High volume, short messages, adversaries who adapt
Messaging platforms, aggregators, operators, payment notification flows — the shape of the problem repeats wherever a short message is cheap to send and expensive to get wrong.
A technical session
Bring your integration points and your traffic profile. We will tell you what is feasible before anyone writes a proposal.
ServicesCustom software
Systems built for a specific operational problem, by a team that will say when something cannot be done.
More workOther case studies
Systems in production, with the figures we are allowed to publish.