Privacy friendly
Notifizz does not store your users’ personal data. Names, plans, segments, custom fields, profile graphs — none of it lives in the platform. When a campaign needs a recipient’s profile, the orchestrator fetches it live from your systems via an enricher, uses it to send the notification, and lets it go. The only customer data Notifizz retains is the strict minimum required to deliver the message and honour later requests (unsubscribe, right of access, right to erasure). That single rule — fetch live, don’t copy — is the core of the architecture. Everything below is what falls out of it: the email hashing story, the bounded cache, the redaction pass, the retention dials. None of it is a configuration option you opt into; it’s how the platform is wired.TL;DR
- No warehouse sync. Customer profiles stay in your systems. The orchestrator fetches what it needs at notification time via enrichers — never copies it.
- Plain email is bounded by a window (default 90 days without a send to the person, configurable down to 7). Past it, the address is masked in Audiences, and what outlives it there is a keyed hash (HMAC), scoped to your organisation — enough to find the person by typing their address, to de-duplicate and to honour a past unsubscribe, never enough to email again. The next send makes the address readable again — see plain email lifecycle. The hash has a term too: 180 days after the last send to the person — or the last time
identify()created an identity for them —, and never before the address is masked, a person known only by their address is removed, and a person known by your user id keeps only that id — except anyone who opted out of something, who keeps their hash for as long as the opt-out stands. Copies kept elsewhere — an in-app inbox message that displays the address, the exceptions listed under erasure — follow their own term. - Expired messages are redacted, not deleted. Everything that names the person is emptied; the delivery record survives so your Outbox keeps telling the truth about what shipped. It keeps a one-way reference to the person, used only to honour access and erasure requests — the person’s campaign history, shown to your team —, to attribute conversions and to count each person once in your campaign statistics (aggregated, never shown per person), until it is deleted 180 days after sending.
- The enricher cache is bounded, not a sync. Per
(org, env, enricher, params)keying with a TTL declared at registration. Eviction is automatic; only recently used records exist. - Five retention dials, configured per organisation, with conservative GDPR-aligned defaults and platform-enforced bounds.
- Email opens and clicks are measured only with consent. Only recipients covered by your organisation’s declaration are measured — everyone under All my recipients have consented, the people whose consent your backend passed on under Only those who consented — and never someone who refused, whether your backend passed the refusal on or the person gave it from an email. Until your organisation declares, production emails carry no open pixel and record no opens or clicks; links and unsubscribe keep working. See open and click measurement.
Why it matters
GDPR Article 5 — and the equivalent regimes everywhere else — require you to hold customer data only as long as you need it, for explicit purposes. Notification platforms in the Customer.io / Braze / Iterable lineage centralise all customer data in their own database, indefinitely, in case a campaign ever fires for that customer. Your DPO ends up auditing a parallel customer graph that exists only for “we might send something one day”. Notifizz’s design eliminates that parallel graph. The privacy surface you have to audit is the event payloads you control, plus the per-message delivery snapshots — not a copy of every customer.The three pillars
1. Enrichers — no warehouse copy
The platform doesn’t sync your customer database. Instead, the orchestrator calls enrichers — server-side functions you register that fetch live data from your systems at notification time.- Privacy surface stays in your systems. Notifizz processes; you store.
- No drift. The user’s email is whatever your DB returns at notification time, not what last night’s sync ran with.
- No schema migration. New attribute? Add a field to the enricher’s output. Renamed? One file changes.
2. Email hashing — plain text only when needed
The platform handles email in two distinct states: plain during the operational window, hashed only outside it. The suppression list stores hashes only, and an unsubscribe is recorded on the person’s subscription preferences and matched by the hash too — neither needs the plain address to hold.Normalisation, then hash
Every incoming email is normalised — trimmed and lower-cased — then hashed with a keyed hash (HMAC-SHA-256) under a secret key that Notifizz holds: without that key, nobody can recompute it from a list of addresses. The hash is scoped to your organisation: the same address in two different organisations produces two different hashes, so nothing correlates across customers of the platform. The hash is what makes the rest work. It de-duplicates a person arriving through several ingest paths, and it lets the platform recognise “this address unsubscribed” long after the address itself is gone.Plain email lifecycle
The plain email is held for the window after the last send to the person — or the last time your backend declared a new identity for them withidentify() — and for as long as an email or web push that has not been redacted yet still names it — an in-app inbox message names its recipient by user id only (see redaction). Erasing the person erases that message through the address. Past both, a daily job masks it automatically: Audiences and the export show j•••@acme.com instead of the address — or, in the Audiences list, your user id for a person you identify —, and the plain copy leaves the person’s record; copies kept elsewhere follow their own term (see the exceptions under erasure). The hash stays, up to the hashed-address term (below). Until then, searching by the address still finds the person, and their opt-outs and the suppression list keep applying. When a new send arrives for the same address, the hash matches the existing recipient, the plain email is reintroduced, and the history is continuous.
A send counts from the moment Notifizz prepares it, even when it does not leave: a rehearsal, a sample of a broadcast, or a campaign that is not live yet. A recipient included in one keeps their address for another window.
Hashed address lifecycle
180 days after the last send to the person — or the last timeidentify() created an identity for them —, and only once their plain address has been masked, Notifizz no longer recognises them by their address:
- A person known only by their address is removed — their record, its hash and their preferences. Their Audience goes with it when nothing else is left in it, and so do the statistics records that carry only the person’s one-way reference: the markers that keep a unique open or a conversion from counting twice, the records that stop a sequence once its objective is reached, and the entries of the “Who converted” list that name no one, even before their own term. A measurement consent you sent by address, kept without an Audience, stays as long as another record in its environment holds the same address; an opt-out, wherever it is recorded, is kept for as long as it stands (below).
- A person known by your user id keeps the user id and loses the hashed address. Audiences shows them by your user id, and searching by the address no longer finds them.
identify() does not restart them: only a send, or an identity identify() creates, does. Past them, a send to the address alone starts a new person with a new history — counted as a new person in a campaign that spans both; a send that carries your user id and the address finds the person again and restores the address.
3. Cache — bounded, not a sync
Enricher responses are cached server-side to keep latency low. This is not a sync. The differences are structural:(organisationId, environmentId, enricherName, sha256(params)) — strict cross-tenant isolation, identical params from different organisations never collide. TTL precedence: per-call override → declared at registration → 1-hour default. An enricher declaring cache: false cannot be overridden upward.
The enrichers protocol covers the cache policy in detail.
What Notifizz stores — and what it doesn’t
Retention configuration
GDPR places retention under the responsible-party (you, the controller) — not the processor (Notifizz). Notifizz exposes five configurable dials per organisation, with conservative defaults and platform-enforced bounds:Set by the platform
Some periods are not dials: they are the same for every organisation, and the Retention settings page shows them read-only.Redaction
PastmessageRetentionDays, a sent message is not deleted. Everything on it that names the person is emptied — recipient (your user id and the address), rendered HTML, subject, properties and push payload; the row stays, flagged with a redaction timestamp. The emptied record is deleted in turn 180 days after the message was sent. That duration is set by the platform, not by a dial. Messages sent on or before 29 September 2026 may keep the destinations of their links and buttons — which can carry personal data, a magic sign-in link for instance — until that deletion.
The distinction is operational as much as legal. Deleting the row outright would take the delivery status, the campaign, the step and the timestamps with it — and a delivery report that finds nothing concludes that everything went fine, including for sends where not a single message ever left. A redacted record still says what happened. It no longer names anyone.
The redaction flag is what separates a record that was emptied from one that never carried anything — without it, “absent” and “blank” would be indistinguishable, which is the exact trap the redaction pass exists to close.
In-app inbox messages are the deliberate exception: an inbox is a reading surface, so its entries are kept for notificationCenterRetentionYears and then deleted outright. A message someone is meant to read makes no sense emptied of its content. An entry keeps only what that notification shows — its template, the values it displays and its button links — and the user id it is addressed to. It does not keep the rest of the recipient’s profile, and it keeps their email address only if that notification displays it. Entries written before October 2026 were reduced the same way by a one-off clean-up pass.
What a redacted record still points to
A redacted record keeps a one-way reference to the person it was sent to: a pseudonym, specific to your organisation. Nothing turns it back into a name, an address or a user id — not the record, and not Notifizz. It only works the other way round: starting from a person still on file in your organisation, Notifizz can recognise the records that point to them. The reference serves to honour access and erasure requests, to attribute conversions and to count each person once in your campaign statistics (aggregated, never shown per person) — nothing else:- Access goes all the way. The person’s campaign history — on their record in Audiences, shown to your team, and your answer to a right-of-access request for what was sent — lists their redacted records alongside the others: campaign, channel, status and date, never the content. That is the 100 most recent deliveries, up to 180 days.
- Erasure goes all the way. When you erase a person — the whole person, or the last channel identity they had — their redacted records are found through the reference and deleted with them, instead of waiting out their 180 days. So are the statistics records that carry only the reference: the markers that keep a unique open or a conversion from counting twice, and the records that stop a sequence once its objective is reached.
- Conversions are attributed. When one of your events reports that the person converted, Notifizz still recognises them as someone the campaign wrote to after the message is redacted, and a sequence set to end when the objective is reached stops for them — for as long as the record exists, up to 180 days after sending. That window follows the record and is not configurable.
- Statistics count people, not records. Your campaign statistics recognise the person behind a redacted record through the reference, so a person still counts once after redaction: a click on a redacted web push counts under them, and the delivery figures of a run in the Outbox or of a broadcast report count people, not records. These figures are aggregated: the reference is never shown per person.
identify() merges two Audiences, Notifizz remembers that the absorbed one now leads to the surviving one, so erasing the survivor reaches the redacted records of both, and its campaign history lists them. detach() usually corrects a mistaken link, so it forgets every merge into the Audience the identity leaves — merges made in good faith included, since nothing records which merge brought which identity. Redacted records sent under an absorbed Audience, before its merge, are then reached by no erasure and listed in no campaign history — neither the detached identity’s nor the survivor’s. They name no one, and they are still deleted 180 days after sending. Records sent to the detached identity while the mistaken merge was in place follow it as long as they name it; once redacted, they name no one and stay with the Audience it left: its erasure takes them, its campaign history lists them. The same goes for the markers that keep a unique open or a conversion from counting twice under that absorbed Audience: they name no one either, and they are deleted 90 days after the campaign is archived.
Measurement after redaction
- An email is no longer measured. An open or a click on a redacted email is not recorded, whatever your organisation declared for open and click measurement: the record no longer says who received it, so Notifizz can no longer check that this person may be measured. Its links keep working, and its line in the person’s campaign history keeps the status it had when it was redacted.
- A web push is still measured. Its clicks keep counting. The reason email stops does not apply here: the measurement setting covers email only.
Suppression and right to be forgotten
When a user unsubscribes, marks a message as spam, or asks to be deleted, the obligation is “never email again” plus (for deletion) “remove the record”. Notifizz handles both without keeping the address indefinitely:- Unsubscribe, from the link in an email or the one-click header → recorded on the person’s own subscription preferences, not on the suppression list. Before a promotional send, the incoming address is hashed and matched against those preferences, so the plain email is not needed. The opt-out holds until the person re-subscribes from the preference centre; transactional mail still goes out.
- Spam complaint, hard bounce, or an address your organisation adds itself → the email is hashed and added to the per-org suppression list. Subsequent sends hash the incoming address and check the list before dispatch. The plain email is not retained. Each entry is kept for a set number of years, then removed; a bounce is lifted earlier if the provider reactivates the address.
- Right to erasure → declared by your system as part of your own user-deletion flow. Three routes, depending on what you are erasing:
- the event log behind your counters, about three to four months (see the table above);
- what the internal queues still hold for them — a send, or the event behind a reminder or a digest: about two days after that work finished (see the table above);
- once a person’s address has been masked: their conversions and objective evaluations that name them only by that address — not by your user id — until their own term; erasure no longer holds the address to find them by;
- a one-way reference to the erased user id — a keyed hash, never the id — that stops the sequences already running for them (below), for as long as a sequence that started before the erasure is still running;
- on a sequence still running for them: the event that started it, and, for each step it still plays, what your enrichers returned about them and which of your conditions applied to them — kept with the sequence: 180 days after it started, or until it ends if that is later;
- an objective evaluation that names the person only through your own event properties, or only by push id or phone number — 180 days;
- the statistics of people erased before this behaviour shipped, in October 2026 — until their retention ends.
403, as for anyone unknown, and still stops the sequences already started for them. An event you send after the erasure is new data: the sequence it starts reaches the person and creates a new record. Email stays blocked only if the erased record held their address, which erasure puts on the suppression list. Four limits:
- the stop applies in the environment of the erased record — the suppression of the address, above, applies in all your environments;
- a notification already handed to delivery when the erasure happens — typically seconds before it — still goes out, and creates a new record for them;
- a sequence that starts after the erasure, or while it is being processed, counts as a new sequence even when it was set up before: an inactivity reminder or a digest armed before the erasure, or an event you sent just before it and still waiting to be processed, reaches the person;
- a person erased before this behaviour shipped, in October 2026, can still be reached by a sequence that was already running, until that sequence ends.
How this composes with the rest
- Enrichers — the no-copy primitive, the largest single reason Notifizz is privacy friendly.
- Recipients — recipients carry only
id+email(plus arbitrary fields you control); never absorbed into a profile store. - Authentication — widget auth modes keep authenticated and anonymous traffic strictly separated, in line with the CNIL January 2026 recommendation.
- Open and click measurement — whether your emails carry an open pixel and record clicks is your organisation’s declared instruction, dated and journaled, closed by default — refined person by person by the consent or refusal your backend passes on.
- Activity log — the audit trail of campaign work. Organisation-level choices — retention dials, open and click measurement — keep their own journals.
FAQ
If you don't store profile data, how do you display a recipient's name in the dashboard?
If you don't store profile data, how do you display a recipient's name in the dashboard?
external_id: display degrades, the platform doesn’t block. Once a person’s address is masked, the resolver is no longer given it: a resolver that looks people up by address returns nothing for them until the next send, and a person known only by a masked address is not called at all.Why hash the email instead of just deleting it?
Why hash the email instead of just deleting it?
Why is the hash scoped per organisation?
Why is the hash scoped per organisation?
The enricher cache holds data — isn't that a sync I have to audit?
The enricher cache holds data — isn't that a sync I have to audit?
cache: false at registration — the orchestrator will hit your endpoint on every call.What happens when I run a marketing campaign to 50,000 customers? You'd need their emails for hours.
What happens when I run a marketing campaign to 50,000 customers? You'd need their emails for hours.
Can I export everything Notifizz holds about a specific user?
Can I export everything Notifizz holds about a specific user?
identify(). It does not contain their messages, neither the delivery history nor the in-app inbox. What was sent to the person is the campaign history on their record in Audiences — the 100 most recent deliveries, up to 180 days, redacted ones included; the content of a message opens one message at a time in the Outbox, which lists runs by campaign and event, not by person, for as long as it is held: an email or a web push is redacted after messageRetentionDays (7 days by default), an in-app inbox message is kept for notificationCenterRetentionYears. See answering a right-of-access request.GDPR puts retention on the controller — what's Notifizz's role exactly?
GDPR puts retention on the controller — what's Notifizz's role exactly?
Does Notifizz know when my recipients open an email or click a link?
Does Notifizz know when my recipients open an email or click a link?
Can the Notifizz team read the messages we send?
Can the Notifizz team read the messages we send?