I pay $0/month for my newsletter. I used to pay $29/month on MailerLite.
Annual savings: $348.
Subscribers: 1,923.
Open rate: 32% (vs 21% industry average).
MailerLite isn't bad. It's excellent. The problem is that you don't need to pay for something you can self-host for free.
Here's how I migrated from MailerLite to Listmonk, how long it took, and why my open rate actually went up after the migration.
The Problem: Newsletter SaaS Is Expensive
Typical pricing (2026):
- MailerLite: $29/month for ~2K subs
- Mailchimp: $45/month
- ConvertKit: $66/month
Annual cost: $348-$792.
For what? Sending emails, basic templates, stats (opens, clicks).
Reality: You can do ALL of that with open source software + a $12/month VPS (that you probably already have for other services).
The Solution: Listmonk (Self-Hosted)
Listmonk is an open source newsletter platform:
- ✅ Unlimited campaigns
- ✅ Unlimited subscribers
- ✅ Customizable templates
- ✅ Complete stats (opens, clicks, bounces)
- ✅ Multi-list support
- ✅ Segmentation
- ✅ Complete API
- ✅ Docker-ready
Cost: $0/month (just hosting, which you already have).
Setup time: 2 hours (one-time).
The Migration: MailerLite → Listmonk
1. Export from MailerLite
MailerLite dashboard → Subscribers → Export → CSV
Output: subscribers.csv with email, name, status, subscribed date.
2. Setup Listmonk (Docker)
version: '3.8'
services:
postgres:
image: postgres:15
container_name: listmonk_db
restart: always
environment:
POSTGRES_USER: listmonk
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: listmonk
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- listmonk_net
listmonk:
image: listmonk/listmonk:latest
container_name: listmonk
restart: always
ports:
- "9000:9000"
depends_on:
- postgres
environment:
LISTMONK_app__address: "0.0.0.0:9000"
LISTMONK_db__host: postgres
LISTMONK_db__port: 5432
LISTMONK_db__user: listmonk
LISTMONK_db__password: ${POSTGRES_PASSWORD}
LISTMONK_db__database: listmonk
LISTMONK_app__admin_username: ${ADMIN_USER}
LISTMONK_app__admin_password: ${ADMIN_PASSWORD}
networks:
- listmonk_net
volumes:
postgres_data:
networks:
listmonk_net:
driver: bridge
docker-compose up -d
3. Reverse Proxy with Caddy
listmonk.yourdomain.com {
reverse_proxy localhost:9000
}
caddy reload
Result: https://listmonk.yourdomain.com with automatic SSL.
4. Import Subscribers
Listmonk UI → Create list → Subscribers → Import → Upload CSV → Map columns.
Result: 1,923 subs imported in 30 seconds.
5. Create First Campaign
Send a brief note to subscribers letting them know about the platform change. Nothing fancy — just transparency.
Results: Open Rate Actually Went Up
| Metric | MailerLite (before) | Listmonk (after) |
|---|---|---|
| Open rate | 28% avg | 32% avg (+4%) |
| Click rate | 6% | 8% (+2%) |
| Deliverability | 95% | 97% |
Why did it improve?
1. Plain Text Emails
MailerLite templates = heavy HTML with images and styled buttons.
My Listmonk setup = plain text with minimal HTML.
Result: ISPs trust plain text more (fewer spam flags).
2. Full Sender Control
MailerLite = shared IP pool (your deliverability depends on other users).
Self-hosted Listmonk = your own server, your own reputation.
Setup dedicated SMTP with proper SPF, DKIM, DMARC configuration.
3. No "Marketing Template" Vibes
MailerLite templates scream "EMAIL BLAST."
My Listmonk template = personal email with light formatting.
ISPs detect: Email from a real person > marketing blast.
Automation: OpenClaw + Listmonk API
Workflow:
- Publish blog post on WordPress
- OpenClaw detects new post (webhook)
- Extracts title, excerpt, URL
- Generates email version (using best writing model)
- Creates Listmonk campaign (API)
- Schedules for next day 9 AM
import requests
LISTMONK_URL = "https://listmonk.yourdomain.com"
campaign_data = {
"name": f"Newsletter: {post_title}",
"subject": generated_subject,
"body": email_html,
"lists": [1], # List ID
"type": "regular",
"content_type": "html",
"send_at": "2026-02-19T09:00:00Z"
}
response = requests.post(
f"{LISTMONK_URL}/api/campaigns",
json=campaign_data,
auth=(LISTMONK_USER, LISTMONK_PASS)
)
Result: Blog post → Newsletter (zero manual clicks).
Minimal Template (My Setup)
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Georgia, serif; max-width: 600px; margin: 0 auto; padding: 20px; color: #333; }
h1 { font-size: 24px; color: #000; }
p { line-height: 1.6; margin-bottom: 15px; }
.footer { color: #666; font-size: 14px; margin-top: 40px; }
</style>
</head>
<body>
<h1>{{ .Campaign.Name }}</h1>
{{ .Campaign.Body }}
<div class="footer">
<p>You're receiving this because you subscribed at cristiantala.com.</p>
<p><a href="{{ .UnsubscribeURL }}">Unsubscribe</a></p>
</div>
</body>
</html>
Key Lessons
Subject Lines Need a Human Touch
Tested AI-generated subject lines for 10 newsletters:
- AI subjects: 24% open rate
- Human subjects: 35% open rate
AI can write the body. Subject lines need human instinct.
Send Time Matters
- 6 AM: 18% open (too early)
- 9 AM: 35% open ✅
- 2 PM: 22% open (inbox already full)
- 6 PM: 12% open (disconnection mode)
Consistency > Frequency
Before: Newsletter every 2 weeks (inconsistent).
After: Newsletter every Monday at 9 AM (clockwork).
Open rate went up 8% from consistency alone.
Why: Readers expect the email. If it arrives when expected, they open it.
Costs: $0 vs $348
| Item | MailerLite | Listmonk (self-hosted) |
|---|---|---|
| Monthly | $29 | $0 |
| Annual | $348 | $0 |
| VPS | n/a | $12/mo (shared with 8 other services) |
| Setup time | 0 | 2 hours (one-time) |
Setup payback: Immediate (month 1 saves $29).
Hostinger VPS is what I use — enough power to run Listmonk, n8n, NocoDB, and 5 more services on a single instance.
When NOT to Self-Host
Don't self-host if:
- <500 subs (free SaaS tiers work fine)
- You don't know Docker (learning curve isn't worth $29/month)
- You need advanced features (automatic A/B testing, ML segmentation)
- You don't have a VPS (buying one just for a newsletter doesn't make sense)
Do self-host if:
- 1,000+ subs (savings >$20/month)
- You already have a VPS (marginal cost = $0)
- You know basic Docker (or want to learn)
- You value full control (data ownership, deliverability)
Migration Checklist
- [ ] Export subscribers CSV from your current provider
- [ ] Set up Docker (postgres + listmonk)
- [ ] Configure Caddy reverse proxy
- [ ] Verify SSL works
- [ ] Create main list
- [ ] Import subscribers CSV
- [ ] Configure SMTP + SPF/DKIM/DMARC
- [ ] Create email template
- [ ] Send test campaign to yourself
- [ ] Send migration notice to subscribers
- [ ] Monitor opens/clicks for 3 campaigns
- [ ] Cancel old provider after 1 month testing
Conclusion
Setup time: 2 hours (one-time).
Annual savings: $348.
ROI: $174/hour of setup work.
Bonus: Open rate went up, full deliverability control, data ownership, no vendor lock-in.
2 hours of setup. $348/year saved. Forever.
Do you use a self-hosted newsletter? Which platform? Share in the comments.
📝 Originally published in Spanish at cristiantala.com
Top comments (0)