# How often to re-validate the contact data in your CRM

_2026-10-01 · Boundstone (https://boundstone.io/blog/how-often-to-revalidate-crm-data)_


Most teams validate contact data once, at import, and never again. The logic is reasonable — you cleaned it on the way in — but it produces an odd result: the records that have been in the CRM longest, and are therefore most likely to have decayed, are the ones nobody has checked since the day they arrived.

Validation is a reading, not a property. It describes a moment.

## What decays, and how fast

**Email syntax: never.** A well-formed address stays well-formed. This is the only part that is genuinely permanent.

**Mail-server presence: slowly, then suddenly.** MX records are stable for years and then are not — a company folds, migrates, or lets a domain lapse. A live MX lookup is the cheapest re-check you can run and it catches the whole class.

**Disposable and role status: slowly.** New throwaway domains appear constantly, so a domain that was unknown last year may be catalogued now. Role addresses rarely stop being role addresses.

**Phone numbering-plan metadata: barely at all.** A range designated `mobile` stays designated `mobile`. This is exactly why a phone record validated two years ago still validates — and why that tells you very little.

**Whether a specific line is live: continuously.** Disconnection and porting happen every day and are invisible to a metadata check by construction. `carrier_lookup`, `ported_status` and `hlr_liveness` are marked `not_performed` for precisely this reason: the API is telling you the one thing that decays fastest was not measured.

## Re-check at the moment of use

The cadence question is usually framed as an interval — monthly, quarterly. A better frame is a trigger.

**Before a send or a calling block.** This is the check that matters, because it is the one that is current when it counts. A validation from three months ago describes the list three months ago.

**When a segment wakes up.** Dormant records are the highest-decay population you own. Anything that has not been touched in a year should be screened before it is, not after.

**On bounce or disconnect signals.** A hard bounce is evidence about the domain, not just the address. Re-screen the neighbours.

**Never on a schedule alone.** Re-validating a segment nobody is about to contact spends credits to update a field nobody will read.

## Doing it without re-cleaning everything

`POST /v1/bulk/email` and `POST /v1/bulk/phone` take the segment rather than the database — 250 rows per job on the free tier, 10,000 on a paid plan, one credit per row and refunded on any row that errors.

Write the verdict and the validation date back onto the record. The date is the part teams skip and the part that makes the next decision possible: without it, nobody can tell a record checked yesterday from one checked at import in 2024, and the whole system degrades into guessing.

If the segment is one where liveness genuinely decides the spend, `hlr:true` runs a live network dip at 5 credits on a paid plan and moves `carrier_lookup`, `ported_status` and `hlr_liveness` into `checks.performed`. Abstentions are refunded. That is worth doing on the rows about to receive paid contact, and rarely worth doing across a database.

## What re-validation cannot fix

It removes the provably bad, not the merely stale. An address at a live domain belonging to someone who left the company two years ago validates cleanly, because every check it fails is a check nobody can run from outside — `smtp_mailbox` and `catch_all` are `not_performed`, and the person's departure is not a DNS fact.

Re-validation narrows the population that is definitely wrong. It does not produce a population that is definitely right, and any cadence built on believing otherwise will disappoint on schedule.

## The short version

- **Validation is a reading, not a property.** It describes the moment it was taken and decays from there.
- **The oldest records are the least-checked.** Import-only validation inverts the risk exactly.
- **Different facts decay at different speeds.** Syntax never; MX slowly then suddenly; a specific line's status continuously.
- **Trigger beats interval.** Re-check before a send or a calling block, and when a dormant segment wakes up.
- **Write the date back with the verdict.** Without it, nobody can tell a fresh record from one checked at import.
- **Dip only what is about to be paid for.** `hlr:true` at 5 credits, refunded on abstain, on the send segment rather than the database.
- **It removes the provably bad, not the merely stale.** A live domain and a departed employee both pass.
