listmonk icon indicating copy to clipboard operation
listmonk copied to clipboard

Timezone-aware Campaign Scheduling

Open githubcom13 opened this issue 9 months ago • 1 comments

Description

I propose adding a feature to Listmonk that allows scheduling email campaigns based on each subscriber's timezone, stored as an attribute or a dedicated field in the subscribers table. This would enable sending emails at a precise local time for each subscriber (e.g., 10:00 AM in their timezone), improving deliverability and open rates while reducing queue bottlenecks caused by long, uniform send lists.

Problem

Currently, Listmonk schedules campaigns at a single UTC time (send_at) for all subscribers in a campaign, regardless of their location. This can lead to:

  • Suboptimal open rates: Emails may arrive at inconvenient times (e.g., midnight) for subscribers in different timezones.

  • Queue overload: Sending all emails simultaneously creates large queues, potentially throttling delivery with SMTP providers like Postmark.

  • Deliverability risks: Bulk sends at a single time may increase the chance of being flagged as spam.

Proposed Solution

1. Timezone Collection:

  • Allow capturing a subscriber’s timezone as an attribute (e.g., attribs->>'timezone' = 'Europe/Paris') via:

  • Public subscription forms (e.g., using JavaScript Intl.DateTimeFormat().resolvedOptions().timeZone to auto-detect).

  • Manual entry or API (POST /api/subscribers with attribs).

  • Optionally, add a dedicated timezone column to the subscribers table for permanent storage and indexing.

2. Campaign Scheduling:

  • Add an option in the campaign creation interface (e.g., "Send based on subscriber timezone") with a target local time (e.g., "10:00 AM local time").

  • When enabled, Listmonk calculates the UTC csend_at` time for each subscriber based on their stored timezone and the specified local time.

3. Queue Management:

  • Distribute the campaign send jobs across multiple time slots in the internal queue, avoiding a single large batch.

  • Leverage the existing worker pool to process sends incrementally, reducing SMTP throttling risks.

Benefits

  • Higher open rates: Emails arrive at optimal local times (e.g., morning), increasing engagement.

  • Improved deliverability: Smaller, staggered batches reduce the likelihood of being flagged as spam by SMTP providers.

  • Reduced queue bottlenecks: Spreads the load over time, avoiding long wait times and improving performance.

Implementation Suggestion

Database:

  • Add an optional timezone column to subscribers (e.g., VARCHAR(50) with values like America/New_York), or use attribs->>'timezone'.

Frontend:

  • Extend the campaign form with a checkbox: "Send based on subscriber timezone" and a field for target local time (e.g., "10:00").
  • Update subscription forms to include JavaScript timezone detection:

const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; document.getElementById('timezone').value = timezone;

Backend:

  • Modify the campaign scheduler to:
  1. Query subscribers’ timezones.
  2. Calculate UTC send times per subscriber (e.g., 10:00 Europe/Paris = 09:00 UTC).
  3. Queue individual send jobs with staggered send_at timestamps.

API:

  • Add a timezone_aware boolean to POST /api/campaigns (e.g., { "send_at": "10:00", "timezone_aware": true }).

Example Use Case

  • A campaign targets 10,000 subscribers across 5 timezones (e.g., PST, EST, GMT, CET, IST).
  • User sets "Send at 10:00 AM local time" with timezone_aware: true.
  • Listmonk schedules 2,000 emails per timezone, sending them at:
    • 17:00 UTC (PST: 10:00 AM).
    • 14:00 UTC (EST: 10:00 AM).
    • etc.
  • Result: Emails arrive at 10:00 AM local time for each subscriber, spread over hours, improving open rates and deliverability.

Additional Notes

  • Ensure backwards compatibility: If timezone is missing for a subscriber, fall back to the campaign’s global send_at.
  • Document the feature in the API and UI guides.

Motivation

This feature would make Listmonk a stronger competitor to tools like Mautic or commercial platforms (e.g., Mailchimp), where timezone-aware sending is a standard for maximizing engagement and deliverability.

githubcom13 avatar Mar 27 '25 19:03 githubcom13

Hi @githubcom13, while this is an interesting proposal, the queuing logic you are proposing is fundamentally incompatible with how it works currently.

listmonk handles campaigns serially (once a campaign starts, it iterates through 0-n ordered subscriptions until the campaign ends by reaching n), and processes at a campaign->n lists level. It paginates from 0-n and uses a checkpoint mechanism to track progress, which fully depends on the records being sequential. A significant number of optimisations have been done to make this model work performantly. Changing it to do scheduling per subscriber, I would think, is outright impossible, without rewriting the entire scheduling core and logic.

knadh avatar Mar 29 '25 06:03 knadh

This issue has been marked 'stale' after 90 days of inactivity. If there is no further activity, it will be closed in 7 days.

github-actions[bot] avatar Jun 28 '25 02:06 github-actions[bot]