-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Open
Labels
Description
Bug Description
When modifying the lists associated with a draft campaign (adding or removing lists), the to_send field is not recalculated. The to_send value is set only when the campaign is first created and remains static even if the actual number of subscribers changes due to list modifications.
Steps to Reproduce
- Create a new draft campaign
- Associate it with List A (e.g., 100 subscribers)
to_sendis set to 100
- Save the draft
- Edit the draft campaign and add List B (e.g., 50 more subscribers)
- Check the campaign details
Expected Behavior
After adding List B:
to_sendshould be recalculated to 150 (100 + 50)- The campaign should reflect the actual number of recipients
Similarly, when removing a list:
to_sendshould decrease accordingly
Actual Behavior
to_sendremains at the original value (100)- The database shows the correct list associations in
campaign_lists - When the campaign is sent, it may send to more (or fewer) subscribers than indicated by
to_send
Database Evidence
listmonk=# SELECT
c.id,
c.name,
c.to_send as "to_send_actual",
COUNT(DISTINCT sl.subscriber_id) as "suscriptores_reales"
FROM campaigns c
INNER JOIN campaign_lists cl ON c.id = cl.campaign_id
INNER JOIN subscriber_lists sl ON cl.list_id = sl.list_id
WHERE c.id in (9,29) -- Reemplaza con ID de tu campaña
AND sl.status = 'confirmed'
AND c.status = 'draft'
GROUP BY c.id, c.name, c.to_send;
id | name | to_send_actual | suscriptores_reales
----+---------------------------------------+----------------+---------------------
29 | Convocatoria BUSSINES ÁREA FITUR 2026 | 320 | 310Impact
- User confusion: The UI shows incorrect recipient counts
- Campaign planning: Users cannot trust the
to_sendnumber for estimation - Reporting: Analytics show "Sent: 150 / To send: 100" which is misleading
- Resource allocation: Cannot properly estimate send time/load
Environment
- Listmonk version: v5.1.0 (30846f8 2025-09-09)
- Database: PostgreSQL
- Deployment: Docker
Proposed Solution
Option 1: Recalculate on save (Recommended)
When a draft campaign is saved after modifying lists, recalculate to_send:
func (c *Campaign) RecalculateToSend() error {
if c.Status != CampaignStatusDraft {
return nil // Only for drafts
}
query := `
SELECT COUNT(DISTINCT sl.subscriber_id)
FROM campaign_lists cl
INNER JOIN subscriber_lists sl ON cl.list_id = sl.list_id
WHERE cl.campaign_id = $1
AND sl.status = 'confirmed'
`
var count int
err := db.QueryRow(query, c.ID).Scan(&count)
if err != nil {
return err
}
c.ToSend = count
return c.Save()
}Option 2: Calculate on-demand
Don't store to_send for drafts, calculate it when displaying:
- Store
to_sendonly when campaign starts - For drafts, show calculated count in real-time
Option 3: Show warning
If to_send doesn't match actual count, show warning in UI:
⚠️ Recipients changed since campaign was created. Expected: 150, Stored: 100
Current Workaround
Manually update in database:
UPDATE campaigns
SET to_send = (
SELECT COUNT(DISTINCT sl.subscriber_id)
FROM campaign_lists cl
INNER JOIN subscriber_lists sl ON cl.list_id = sl.list_id
WHERE cl.campaign_id = campaigns.id
AND sl.status = 'confirmed'
)
WHERE id = 20 AND status = 'draft';Related Issues
This may be related to:
- List management not triggering campaign updates
- Draft campaigns not being "live" objects
- Missing event hooks when lists are modified
Additional Context
This becomes especially problematic when:
- Adding/removing lists multiple times
- Subscribers are added/removed from lists while campaign is draft
- Using the "Start campaign" button with incorrect recipient count