verifence ← All posts
· 4 min read

Why Verifence never stores a phone number

Verifence rate-limits, scores, and blocks phone numbers it never keeps. The number is hashed into an opaque key before it touches Redis, and the plaintext is discarded on the same request that received it. You don't need to store a number to protect against it.

Hash before you key

Every counter, every reputation lookup, every velocity window is keyed on a phoneKey — a hash of the number, not the number itself.

Rate-limiting only needs a stable identifier: the same input must map to the same bucket. A hash does that perfectly. Two sends to the same number land on the same counter whether or not we can read the digits.

So the entire engine runs on hashes. There is no table of phone numbers anywhere, because there was never a reason to write one.

Logs that hold nothing

Storing nothing is only half of it. The other half is logging nothing sensitive, and that's where most systems quietly leak.

Verifence configures redaction up front. Phone numbers, client IPs, and API keys never reach a log line. Error logs capture the exception class and message with care — and never the Redis DSN, which carries the password.

The failure mode we designed against is the 3 a.m. stack trace that dumps a connection string into your log aggregator. It can't happen here, because the DSN is never in the log path to begin with.

No accuracy tax

The usual objection: surely you give something up by not keeping the raw data?

You don't. A hash is a perfect equality check, and equality is all rate-limiting and reputation scoring require. We never need to ask "what number is this?" — only "have we seen this exact input before, and how often?" A phoneKey answers that with zero loss.

The signals that catch fraud — velocity per number, confirmation rate per network, send spikes to new ranges — are all counts and ratios over stable keys. None of them need the plaintext.

Privacy as a property, not a setting

This isn't a compliance checkbox we added late. It's a structural choice baked into the data model.

There is no "disable storage" toggle, because storage was never built. There is no "redact logs" mode to forget to enable, because redaction is the only mode. The safe path is the only path.

The result is a smaller blast radius. A breach of Verifence exposes hashed keys and counters — not a directory of everyone your customers texted. You can't leak what you never held.

That's the whole point of doing it this way: the strongest guarantee is the one the architecture makes for you, not the one you have to remember to turn on.

Related reading

Put a firewall in front of your SMS spend.

250 checks a month, free. Make your first call in minutes.

Get started free