How to Use n8n with ._Template 49 Annual Checkin Reminder Scheduler
Every year, dozens of relationships quietly go cold: the client you onboarded eleven months ago, the contract that auto-renews unless someone objects, the compliance review that legal expects "sometim
Every year, dozens of relationships quietly go cold: the client you onboarded eleven months ago, the contract that auto-renews unless someone objects, the compliance review that legal expects "sometime in Q3." Nobody forgets on purpose. The task simply has no home — it lives too far in the future for any task list and too infrequently for any recurring habit. An annual check-in reminder scheduler in n8n solves exactly this: it watches your records, calculates when each anniversary falls, and pings the right person at the right time without anyone holding it in their head.
The Problem: One-Year Reminders Fall Through Every Crack
Calendar reminders don't scale. Set fifty of them by hand and you'll misfire half — wrong date, wrong owner, or deleted during a calendar cleanup. Worse, the data that determines when to reach out already lives somewhere: a signup date in your CRM, a contract start in a spreadsheet, a renewal field in your billing tool. Manually copying those dates into a reminder system means the reminder and the source of truth drift apart the moment anything changes.
The other failure mode is the "check every day" reflex — a human or a crude script scanning a whole table daily, eyeballing which anniversaries are near. It works until the list grows, the person goes on vacation, or the logic ("11 months out, not 12") lives only in someone's memory. What busy ops teams actually need is a system that reads the authoritative date, does the anniversary math correctly (including the leap-year edge case), and fires a notification on a schedule you never have to babysit.
The Solution: A Date-Aware Scheduler in n8n
Template 49 wires together four capabilities n8n gives you out of the box: a time-based trigger, a data source read, date arithmetic, and a notification action. The scheduler wakes up on a fixed cadence — daily is the right default — pulls every record with an anchor date, and asks a single question of each: is today the reminder day for this record's next annual check-in? Records that match get routed to a notification; everything else is silently ignored until tomorrow.
Because the workflow reads the anchor date live each run, it never goes stale. Update a contract start date in your source system and the next reminder recalculates automatically. There is no second list to maintain, no reminder to delete when a customer churns — remove the record and the reminder disappears with it. This is the whole point of doing it in n8n rather than fifty calendar entries: the logic is centralized, the data stays authoritative, and the schedule runs itself.
Step-by-Step Setup in n8n
1. Schedule Trigger. Add a Schedule Trigger node set to a fixed daily time — Trigger Interval: Days, Days Between Triggers: 1, and an hour like 09:00 in your workflow's timezone (set the timezone under workflow Settings so date math stays consistent). Running once a day keeps the workflow cheap and makes every "reminder day" deterministic.
2. Fetch the records. Add the node for your source of truth. For a spreadsheet use Google Sheets → Get Rows; for a CRM use the HubSpot, Pipedrive, or a generic HTTP Request node against your API. Return the anchor date (signup, contract start, last check-in) plus the contact's name and email. Keep the read narrow — only the fields you need for the reminder decision and the message.
3. Compute the next anniversary. Add a Code node (or a Set node with expressions) to derive the reminder date. Using n8n's Luxon-backed date helpers, take the anchor, set its year to the current year, and compare to today. A robust snippet:
const anchor = DateTime.fromISO(item.json.start_date);
const today = DateTime.now().setZone('America/Sao_Paulo').startOf('day');
let next = anchor.set({ year: today.year });
if (next < today) next = next.plus({ years: 1 });
// remind 14 days before the anniversary
item.json.remind_today = next.minus({ days: 14 }).hasSame(today, 'day');
return item;
4. Filter to today's matches. Add an IF node (or the Filter node for batch processing) with the condition {{ $json.remind_today }} is true. Only records whose reminder day is today pass through; the rest end the run quietly.
5. Send the notification. On the true branch, add your action node: Gmail / Send Email, Slack → Send Message, or an HTTP Request to a WhatsApp or webhook endpoint. Personalize with expressions like Hi {{ $json.name }}, it's been almost a year since we started working together…. If you want an internal heads-up instead of contacting the customer directly, point the Slack node at your account-management channel with the record details.
6. Mark it done (optional but recommended). After sending, add a write-back node — Google Sheets → Update Row or a CRM update — to stamp last_reminder_sent. Then add that field to your Code node's condition so a record can't be reminded twice in the same window even if the workflow reruns.
Benefits: Set It Once, Trust It Forever
The immediate payoff is that annual outreach stops depending on memory. Renewals get a nudge before they lapse, onboarded customers hear from you on their anniversary, and compliance reviews surface two weeks ahead instead of two weeks late. Because the anchor dates live in your existing systems, the reminder logic stays in sync automatically — no double bookkeeping.
Operationally, one workflow replaces an unbounded pile of manual calendar entries. Onboard a thousand customers and the workflow handles a thousand anniversaries with zero extra setup. The Filter-then-notify pattern keeps runs cheap: even a large table produces notifications only on the handful of days something is actually due. And every reminder is visible and auditable in n8n's execution log, so you can prove a check-in fired — a real advantage over reminders scattered across personal calendars.
Common Pitfalls and How to Avoid Them
Timezone drift. If the Schedule Trigger, the workflow settings, and your date math disagree on timezone, "today" can shift by a day and reminders fire early or late. Set the timezone explicitly in workflow Settings and in every DateTime.now() call, as shown above.
Leap-year and month-end dates. An anchor of Feb 29 or Jan 31 can produce an invalid date when you swap the year. Luxon handles most of this gracefully, but always compare on startOf('day') and test with a Feb 29 record before trusting it in production.
Duplicate sends. If your reminder window is several days wide (e.g., "within 14 days") without a write-back stamp, the same record matches every day in that window and spams the recipient. Use an exact single-day match, or gate on a last_reminder_sent field so each record fires once.
Silent read failures. If the source API rate-limits or returns empty, the workflow completes "successfully" with zero notifications and you never notice. Add an Error Trigger workflow or a Slack alert on the no-rows branch so a broken read is loud, not invisible.
Testing against live contacts. Never debug against real customer emails. Point the notification node at your own address first, confirm the date logic and message render correctly across a few sample anchors, then switch to the live recipient field. Pin the workflow's test data so you can rerun the same records deterministically while you tune the math.
Get the template: The Annual Check-in Reminder Scheduler n8n workflow is ready to import — trigger, date logic, filter, and notification pre-wired. Download it here and have automated anniversary reminders running in under ten minutes.