> ## Documentation Index
> Fetch the complete documentation index at: https://notifizz.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Migration deadline

> Every customer must complete an action themselves before a fixed date. Remind them until they do — and stop the second they do.

## TL;DR

A retail bank retires its old savings account. Every holder has to move their savings to the new contract **themselves**, from the app, before 30 November. Around 40 000 people are affected, they open the app at wildly different rhythms, and nobody who has already moved should hear about it again.

Four settings carry the whole campaign:

| Need                                               | How you do it in Notifizz                                                   |
| -------------------------------------------------- | --------------------------------------------------------------------------- |
| Talk to each customer **once**, not on every login | A **Milestone** synthetic event: threshold `1`, All-time, grouped per user  |
| Remind them on **your** rhythm                     | Five messages and their delays, inside the campaign                         |
| Go quiet the moment they act                       | Objective = the **business event**, plus *ends when → objective is reached* |
| One last push before the date                      | A second campaign on a **Scheduled** synthetic event                        |

## The situation

Banque du Littoral is closing its *Livret Horizon* on 30 November. Nothing happens automatically: a customer who does not transfer in time has their savings parked in a non-interest-bearing holding account until they get around to it. The bank wants to be genuinely helpful about it — insistent with the people who have not moved, and silent with the people who have.

## Why the obvious approach fails

The banking system already knows who still holds an old *Livret Horizon*. It can emit an event saying so — but it emits it **on every login**, dozens of times per person.

Point a campaign straight at that event and Sophie, who logs in most mornings, gets the sequence restarted every morning. Point it at a monthly export instead and you lose the people who signed up last week.

The event is right. Its frequency is not what you want driving your messaging.

## 1. Turn a noisy signal into one entry per person

Create a **Milestone** synthetic event from **Events → New event**:

* **Source event** — the one your system emits when it sees an old contract
* **Thresholds** — `1`
* **Reset** — **All-time**
* **Group by** — user

Notifizz counts the occurrences per person and emits **only on the first one**. Sophie's fiftieth login produces nothing. No code, no release on the banking side: this is dashboard configuration.

<Note>
  The **Group by** field is what makes the counter per-person. Leave it empty and every customer lands in the same counter — the event then fires once for your whole environment and nobody else ever enters the campaign.
</Note>

## 2. Put the rhythm in the campaign, not in the signal

The campaign subscribes to that Milestone event, and holds five messages with their delays:

| When   | Message                         |
| ------ | ------------------------------- |
| Day 0  | Your Livret Horizon is changing |
| Day 7  | How to transfer, in 3 minutes   |
| Day 21 | Five weeks left                 |
| Day 45 | 15 days left                    |
| Day 60 | Last reminder                   |

Marketing edits the copy, the spacing, or the number of messages without a release. Each person walks their own clock from the day they first appeared.

## 3. Stop on the action, never on the read

On the **Recipients** card, set the objective to the business event your app emits when the transfer completes — `savings.migration.completed` — and set **and ends when → the objective is reached**.

The moment Sophie transfers, the remaining messages in her sequence are cancelled. Everyone else keeps theirs.

<Warning>
  Picking **Read** as the objective is the classic mistake on this kind of campaign. Someone opens the message, thinks *I'll do it this weekend*, and never does — you have just gone silent on exactly the person who needed the reminder. The objective must be the **act**, not the fact that a message was opened.
</Warning>

The stop applies to **the sequence in flight**. If your system legitimately re-enters someone later, they start again from the first message — which is why step 1 matters: the Milestone event is what guarantees each person enters only once.

## 4. The collective deadline is a second campaign

The five messages run on each customer's own clock. Someone who first appears on 25 October receives their fifth reminder in December — after the product is gone.

The dated push is a separate campaign, triggered by a **Scheduled** synthetic event on 25 November, sent to the customers who have not migrated. One message, one date, everybody at once.

Two campaigns, two intentions. Neither has to compromise for the other.

## What the bank sets up

* The existing event emitted when a customer still holds an old contract
* A `savings.migration.completed` event emitted when the transfer goes through
* An [enricher](/docs/why/enrichers) returning the holder's first name, the amount sitting on the old account, and the deadline

Notifizz stores none of that. The enricher is called at send time, so every message carries the amount as it is that morning — and the balance never lives in Notifizz.

## Reading the results

On the campaign panel, the **Sends** bar splits into layers. Recipients who did not get the rest of their sequence **because they migrated** appear in their own light-purple layer, above the delivered ones — not in the amber warning layer. Hover the bar to see the breakdown.

A campaign working perfectly therefore shows a bar that is entirely purple, with fewer messages delivered than intended. That is the point: every message not sent is a customer who acted.

## Troubleshooting

<AccordionGroup>
  <Accordion title="A customer received the first message twice">
    The Milestone counter is not grouped per user, or it is grouped on a field the event does not always carry. Open the event and check **Group by** — it must be the identifier present in every occurrence of the source event.
  </Accordion>

  <Accordion title="The sequence does not stop when someone migrates">
    Two usual causes. Either the objective is set to `Read` or `Click` instead of the business event — check the Recipients card. Or the `savings.migration.completed` event does not carry a canonical identity (`id`, `email`, `pushId` or `phone`), so Notifizz cannot match it to the person who received the campaign. See [Objectives](/docs/concepts/objectives).
  </Accordion>

  <Accordion title="Nobody receives anything at all">
    Most often the Milestone grouping key is missing from the event properties. Every occurrence then falls into a single shared counter, threshold `1` fires once for the environment, and no one else ever triggers the campaign. The event panel's live section shows the counters — one line per person is what you want to see, not one line total.
  </Accordion>

  <Accordion title="People who already migrated last month are entering the campaign">
    The Milestone reset is not **All-time**. On **Each month** the counter clears on the 1st and everyone re-enters. All-time never resets.
  </Accordion>
</AccordionGroup>
