Skip to content
All insights
AllClearStack editorial·Reliability··4 min read

Send onboarding reminders only while the next step is useful

Build reminders around the user's unfinished next step, with a fresh eligibility check when the scheduled request arrives.

An onboarding reminder should help someone take a useful next step. It becomes noise if that person has already finished the task, left the workspace or chosen a different path. Scheduling the reminder is straightforward; keeping it relevant is the product work.

Define one next step

Choose a specific action rather than a broad state such as “not activated.” For example, a hypothetical workspace might need its first successful integration before inviting teammates. Define what counts as completion and which conditions should suppress a reminder.

Store those rules in application logic that both the product interface and the reminder receiver can use. If they disagree about completion, users may see a success screen and later receive a message asking them to finish the same task. A single eligibility function makes that disagreement easier to prevent and investigate.

Send an identifier to the future

Create a reminder record with a stable workspace or onboarding-event identifier. Schedule a small payload and let the receiver retrieve current details. Avoid storing a complete message, email address or changing configuration in the scheduled request when the application can supply it later.

Illustrative server-side example: this schedules delivery 24 hours from execution. Replace the environment variables and example record IDs, persist the returned job ID, and implement your own authenticated HTTPS receiver. The request follows the current API reference.

const apiKey = process.env.WEBHOOK_SCHEDULER_API_KEY;
const receiverUrl = process.env.REMINDER_WEBHOOK_URL;
if (!apiKey || !receiverUrl) throw new Error("Set the server-side API key and public HTTPS receiver URL.");

const response = await fetch("https://webhookscheduler.com/api/v1/schedule", {
  method: "POST",
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    url: receiverUrl,
    method: "POST",
    runAt: new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString(),
    reference: "onboarding:example-123",
    idempotencyKey: "onboarding-example-123-reminder-v1",
    body: { resourceId: "example-123" },
  }),
});
if (!response.ok) throw new Error(`Scheduling failed: ${response.status}`);
const job = await response.json();
if (!job.id) throw new Error("Missing scheduled job ID");
// Persist job.id with your business record before acknowledging this work.
console.log(job.id);

The example's fixed record ID is a placeholder. In your application, use the identity of the specific onboarding event and a version for its reminder. Repeating the same scheduling idempotency key recovers the retained original job; it is not a way to change that job into a different reminder.

Check relevance at delivery

Authenticate the incoming HTTP request using the documented signing procedure before trusting its payload. Then find the reminder record, load current workspace state and evaluate eligibility. A missing record or completed step should have an explicit outcome, such as skipping obsolete work, rather than falling through to sending a message.

At-least-once delivery means the receiver may see the same event again. Use a durable event identity to claim the business effect, and use the notification provider's idempotency facility if one is available. A separate database write and provider call still require a recovery policy for uncertain results.

Make stopping visible

When the onboarding step is completed, update the local reminder state. You can also cancel the scheduled job using its stored ID when it is still cancelable. That reduces unnecessary delivery attempts, but the receiver's current-state check remains necessary because cancellation can race with work already in progress.

Keep an operational trail with the intended time, job ID and reason for sending or skipping. That is more useful during a support investigation than a simple count of “notifications sent.” Do not mistake a successful HTTP delivery for evidence that a user completed onboarding.

Keep the workflow small

WebhookScheduler is built by AllClearStack. It can handle the future HTTP call while your application retains the onboarding rules. The tradeoff is an external service dependency, alongside receiver security and reconciliation work you still own.

If an existing background worker can scan a few due reminder records and your timing requirements allow it, use that worker. Start with one useful reminder before building a branching sequence. The webhook scheduling guide collection covers the infrastructure choices once that product behavior is clear.

Disclosure · Built by the AllClearStack team

When ownership is the expensive part

Webhook Scheduler handles delayed HTTP delivery, automatic retries, per-attempt logs, and one-call cancellation. Try a real delivery without creating an account.

Related articles