# Redis for Queue Processing

> AcelleMail's default queue driver is the database — fine for hobby installs, terrible for production. Switching to Redis cuts queue-dispatch latency by 10×, eliminates MySQL's `jobs`-table contention under load, and unlocks better worker auto-scaling. This guide walks the install, the Acelle config, the tuning knobs that matter, and the monitoring hooks.

- Canonical URL: https://acellesend.com/kb/articles/redis-for-queue-processing
- Author: Daniel Reyes, Technical Editor
- Category: Server Management — Cron jobs, queues, Supervisor, Redis, Nginx, performance tuning
- Content type: tutorial · Difficulty: intermediate
- Tags: Acellemail
- Published: 2026-03-24 · Last updated: 2026-08-15
- Reading time: 10 min
- Publisher: AcelleMail Knowledge Base, https://acellesend.com/kb

---

## What this is for

AcelleMail uses Laravel queues to dispatch campaign sends, automation triggers, list imports, and bounce processing asynchronously. The default queue driver is the database (`jobs` table in MySQL) — fine for the smallest hobby installs, but it bottlenecks fast:

- **Polling cost:** each worker polls the `jobs` table every `--sleep=3` seconds with a SELECT FOR UPDATE that briefly locks the table
- **Contention under load:** 15 workers all polling + 1 web request inserting jobs into the same table is a hot lock
- **No native priority:** the database driver iterates jobs in `id` order; switching queues = a separate scan

Redis as the queue driver fixes all three: O(1) push/pop via Redis LIST primitives, no MySQL contention, native per-queue ordering. **At any volume above ~5k sends/day, Redis is the right choice.**

This guide walks the install, the Acelle config, the tuning knobs that matter, and the monitoring hooks.

**Prerequisite:** working AcelleMail install per the [Ubuntu 24.04 canonical guide](https://acellesend.com/kb/articles/install-acellemail-on-ubuntu-2404) — Redis is Step 4 of that guide.

## Step 1 — Install Redis 7

```bash
# Ubuntu / Debian
sudo apt update && sudo apt install -y redis-server
sudo systemctl enable --now redis-server

# Rocky / RHEL
sudo dnf module reset redis
sudo dnf module install -y redis:remi-7.2
sudo systemctl enable --now redis
```

Verify the version + that it responds:

```bash
redis-server --version | head -1     # Expect 7.x
redis-cli ping                       # Expect PONG
```

Don't use anything older than Redis 7 in 2026. Redis 6 is end-of-life; Redis 5 has long been EOL.

## Step 2 — Tell systemd to manage Redis properly (Ubuntu/Debian)

```bash
sudo sed -i 's/^supervised .*/supervised systemd/' /etc/redis/redis.conf
sudo systemctl restart redis-server
```

This lets systemd correctly track Redis health for restart-on-failure semantics. Skip on Rocky — Remi's package is already systemd-supervised.

## Step 3 — Configure AcelleMail to use Redis

Edit `/var/www/acellemail/.env`:

```env
QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null
REDIS_DB=0
REDIS_CACHE_DB=1
CACHE_DRIVER=redis
SESSION_DRIVER=redis
```

> **Use `127.0.0.1`, not `localhost`.** PHP's Redis client treats `localhost` as a Unix-socket hint on some systems; using the IP forces TCP, which is what Redis is configured to accept.

Clear the cached config and restart:

```bash
cd /var/www/acellemail
sudo -u www-data php artisan config:clear
sudo supervisorctl restart acellemail-master:* acellemail-worker:*
```

After the workers restart, queue operations route through Redis. **The web UI should show no difference** — Redis is a drop-in replacement.

## Step 4 — Understand AcelleMail's queue layout

AcelleMail's `routes/console.php` + the shipped supervisor templates show the actual queue names in use:

| Queue | Used for | Throughput |
|---|---|---|
| `default` | Misc Laravel jobs + low-priority Acelle jobs | Low (~1-10/s) |
| `import` | List imports — long-running, single-job-per-import | Very low (1-2 concurrent) |
| `high` | Campaign send jobs from "Priority" campaigns | High (10-100/s) |
| `batch` | Bulk send jobs from normal campaigns | Very high (50-500/s) |
| `single` | Transactional + single-recipient sends | Medium (5-50/s) |
| `automation` | Automation-flow steps for individual subscribers | Medium |
| `automation-dispatch` | Bulk automation trigger evaluation | Medium |

The [supervisor setup](https://acellesend.com/kb/articles/setting-up-queue-workers-and-cron-jobs#step-2--supervisor-the-two-tier-split) splits these into two pools: master handles `import,default`; worker handles `high,batch,single,automation,automation-dispatch`. Don't change the split unless you understand the underlying contention model.

## Step 5 — Redis tuning for the AcelleMail workload

Edit `/etc/redis/redis.conf` (Ubuntu) or `/etc/redis/redis.conf` + `/etc/redis.conf` on Rocky:

### Memory cap

```conf
# Set to ~25% of system RAM as a hard ceiling
maxmemory 2gb

# CRITICAL for queues: never evict queue keys
maxmemory-policy noeviction
```

> **`noeviction` is non-negotiable for queues.** Any other policy (`allkeys-lru`, `volatile-ttl`, etc.) means Redis can silently delete pending jobs when memory pressure rises — campaigns will appear sent but recipients receive nothing. With `noeviction`, Redis returns an error to the producer (the web request) instead, which Acelle handles correctly.
>
> If you also use Redis for cache, **use a separate logical DB** (`REDIS_CACHE_DB=1`) and configure per-DB eviction via `SELECT 1; CONFIG SET maxmemory-policy allkeys-lru` — but the global default must stay `noeviction`.

### Persistence

Redis has two persistence modes — pick based on your tolerance for data loss:

```conf
# RDB snapshots (default) — saves a binary dump every N seconds with M+ changes
save 900 1
save 300 10
save 60 10000

# AOF (Append-Only File) — writes every change to disk
appendonly no
```

For an AcelleMail queue:

- **RDB only** (default) is acceptable. Worst case: lose up to 60 seconds of queue data on power loss = at most a minute of un-sent emails for affected jobs. Acelle's retry logic handles this gracefully (jobs that were enqueued but lost just don't run; the campaign-level state ensures they get re-enqueued on `campaign:rerun`).
- **AOF on** halves throughput but loses at most 1 second on power loss. Only worth it if you cannot tolerate any job loss (rare for email sending).

Don't enable AOF "just in case" — it doubles disk I/O and is rarely needed for queues.

### TCP + I/O

```conf
tcp-keepalive 300
io-threads 4         # If you have ≥ 4 cores
```

`io-threads 4` parallelizes socket reads (Redis 6+ feature). On a 4-vCPU server it gives ~30% throughput gain at high concurrency. Don't set above your core count.

Reload Redis after each change:

```bash
sudo systemctl restart redis-server
```

## Step 6 — Monitoring

The five Redis metrics worth watching:

```bash
# 1. Queue depths — should be 0-100 steady-state
for q in default import high batch single automation automation-dispatch; do
  printf "%-22s %s\n" "$q" "$(redis-cli llen queues:$q)"
done

# 2. Memory usage vs maxmemory
redis-cli info memory | grep -E "used_memory_human|maxmemory_human"

# 3. Commands per second (throughput)
redis-cli info stats | grep total_commands_processed
# Run twice with a 5-second gap, divide the difference by 5

# 4. Slow log — any command > 10ms is suspect
redis-cli slowlog get 10

# 5. Persistence health
redis-cli info persistence | grep -E "rdb_changes_since|aof_enabled"
```

For production, push these to your monitoring stack:

- `redis_exporter` (Prometheus) — runs as a separate process, scrapes Redis INFO every 15s
- Grafana dashboard `redis-exporter quickstart` — drop-in
- DataDog Redis integration — same metrics, fewer moving parts if you're already on DataDog

**Alert thresholds:**

| Metric | Warn | Critical |
|---|---|---|
| Memory usage | > 70% of maxmemory | > 90% |
| Queue depth (any single queue) | > 5,000 sustained 5 min | > 50,000 |
| Slow commands per minute | > 5 | > 50 |
| Connected clients | > 50 (usually ~20 on AcelleMail) | > 200 (indicates a leak) |

## Step 7 — When to add Laravel Horizon (optional)

[Laravel Horizon](https://laravel.com/docs/horizon) is a web dashboard for Redis-backed queues. It's not bundled with AcelleMail, but installs cleanly as a Composer dependency:

```bash
cd /var/www/acellemail
sudo -u www-data composer require laravel/horizon
sudo -u www-data php artisan horizon:install
```

What you get:

- Real-time dashboard at `/horizon` showing per-queue throughput, failed jobs, recent jobs
- Auto-balancing (`balance: auto` in `config/horizon.php`) — dynamically reallocates workers across queues based on load
- Tags + filters — search "all failed jobs for customer X in the last hour"

Trade-off: Horizon's `horizon` daemon **replaces** your supervisor `queue:work` lines. You run a single supervisor entry for `php artisan horizon` and Horizon manages the worker pool internally. If you go this route, delete the Acelle two-tier supervisor configs and put a single Horizon supervisor config in their place. **Don't run both** — they'll fight over jobs.

Recommended if you operate 3+ AcelleMail installs or you need finer per-queue observability. For a single install, the bare supervisor setup is simpler and works.

## Step 8 — When to add a separate Redis box

At Large tier (5M+ sends/month) you start to want Redis on its own host:

- Application server and Redis on separate boxes → web requests don't compete with workers for the Redis socket
- A dedicated Redis box can use 100% of its RAM for cache+queue (vs sharing with PHP-FPM + MySQL)
- Easier to add HA via Redis Sentinel (1 primary + 2 replicas + Sentinel for automatic failover)
- Hosting providers' managed Redis (DigitalOcean Managed Redis, AWS ElastiCache, Hetzner Cloud Redis) is the lowest-ops route

Update the AcelleMail `.env`:

```env
REDIS_HOST=10.0.0.5      # private network IP of your Redis box
REDIS_PORT=6379
REDIS_PASSWORD=...       # set this for any non-loopback Redis!
```

> **If you expose Redis on a public network or even a shared private network, set `requirepass` in `redis.conf` and use `REDIS_PASSWORD` in `.env`.** A passwordless Redis on a public IP is one of the most-scanned exploits on the internet.

See [Scaling for 100K+ Emails Per Day](https://acellesend.com/kb/articles/scaling-for-100k-emails-per-day) for the full multi-box architecture.

## Common issues

| What you see | Likely cause | Fix |
|---|---|---|
| Workers report "Connection refused" to Redis | Redis not running or wrong host/port in `.env` | `sudo systemctl status redis-server`; verify `.env` values; `php artisan config:clear` |
| Queue depth keeps growing despite running workers | Worker pool too small for load | Increase supervisor `numprocs`; consider Horizon `balance: auto` |
| "Jobs being run twice" (recipients get duplicate emails) | Worker `--tries` was changed from 1 to ≥ 2 | Restore `--tries=1` in supervisor config; jobs that fail under tries=2 risk duplicate sends on retry |
| Out of memory error from Redis | `maxmemory` too low, or queue backlog grew | Increase `maxmemory`; verify `maxmemory-policy=noeviction` (so jobs aren't silently lost); diagnose backlog source |
| `redis-cli` works but app can't connect | Redis bound to `127.0.0.1` but app uses different network namespace | Verify `bind 127.0.0.1` matches what app uses; for Docker, change to `bind 0.0.0.0` + use internal network |
| AOF growing huge | AOF rewrite cron not running | `redis-cli BGREWRITEAOF`; or disable AOF if not needed |
| All queues empty but campaigns stuck | Cron stopped firing (campaign:schedule isn't dispatching) | Check cron is running per [supervisor + cron guide](https://acellesend.com/kb/articles/setting-up-queue-workers-and-cron-jobs#step-1--system-cron) |

## FAQ

**Can I use Memcached instead of Redis?** Technically — for cache yes; for queues no. Laravel's queue system supports Redis + database + SQS + Beanstalkd, not Memcached. Stick with Redis.

**What about KeyDB / Dragonfly / Garnet?** All three are Redis-API-compatible alternatives that claim higher throughput. They work with AcelleMail (since Laravel just speaks the Redis protocol), but the community is smaller and edge-case compatibility isn't perfect. For a small-to-medium AcelleMail install, vanilla Redis is the safer choice; consider alternatives only if you hit a real throughput wall.

**Redis on the same host as MySQL — is that bad?** Fine at Small + Medium tier. At Large tier, separate them — Redis's tcp keepalives + MySQL's connection pool can compete for file descriptors at high concurrency.

**How do I clear all queues without restarting?** `redis-cli FLUSHDB` clears the current DB. Be very careful — this deletes all pending jobs (you'll lose any unsent emails currently queued). Better: use `php artisan queue:flush` which only clears failed jobs.

**Redis 6 vs 7 vs 8?** Use 7.x. Redis 8 was released June 2024 with significant changes (AGPL licence, JSON/Search/TimeSeries built in); it works but the ecosystem hasn't caught up. Most Redis-as-a-service offerings as of 2026 are still on 7.

**Why does AcelleMail use `--sleep=3`?** Without `--sleep`, an empty-queue worker spins at 100% CPU polling for jobs. `--sleep=3` makes it wait 3 seconds between polls when the queue is empty, dropping CPU to ~0% during idle periods. With Redis + Lua-based BLPOP this is less critical than with database polling, but the 3-second sleep is harmless and consistent with Acelle's templates.

## Related articles

- [Setting Up Queue Workers and Cron Jobs](https://acellesend.com/kb/articles/setting-up-queue-workers-and-cron-jobs) — the supervisor setup that uses Redis (this article's main consumer)
- [Install AcelleMail on Ubuntu 24.04 LTS](https://acellesend.com/kb/articles/install-acellemail-on-ubuntu-2404) — Step 4 of the install
- [Scaling for 100K+ Emails Per Day](https://acellesend.com/kb/articles/scaling-for-100k-emails-per-day) — when to split Redis to its own box
- [Automated Database Backups](https://acellesend.com/kb/articles/automated-database-backups) — separate concern but same ops cadence
- [Post-Install Hardening Checklist](https://acellesend.com/kb/articles/post-install-hardening-checklist) — securing Redis (firewall + auth)
- [Docker Deployment Guide for AcelleMail](https://acellesend.com/kb/articles/docker-deployment-guide-for-acellemail) — Redis as a compose service
- [Server Requirements and Hosting Options](https://acellesend.com/kb/articles/server-requirements-and-hosting-options) — when "Redis on the same box" stops scaling

---

## Related articles

- [Scaling AcelleMail for 100K+ Emails Per Day](https://acellesend.com/kb/articles/scaling-for-100k-emails-per-day): At 100K sends/day you cross the threshold where the default AcelleMail config starts to drag — queue depths climb, MySQL slow queries appear, occasional PHP-FPM 502s. This guide walks the bottleneck math, the configs to tune (queue pool size, MySQL InnoDB, PHP-FPM, nginx, Redis), when to split components onto separate hosts, and the cost/benefit at each step.
- [Setting Up Queue Workers and Cron Jobs](https://acellesend.com/kb/articles/setting-up-queue-workers-and-cron-jobs): AcelleMail uses Laravel queues + a system cron to do everything beyond rendering web pages — sending campaigns, processing automations, handling bounces, refreshing stats, dispatching scheduled sends. This guide walks the production-correct two-tier supervisor split (master + worker), the cron schedule, and the operational discipline that keeps the queue healthy under load.
- [Automated Database Backups for AcelleMail](https://acellesend.com/kb/articles/automated-database-backups): The first backup is the cheapest you'll ever take. By the time you actually need to restore, the cost of NOT having a backup is hours of downtime, lost subscribers, and a furious customer-success conversation. This guide walks the production-correct backup setup: daily mysqldump with rotation, offsite copies, file-tree snapshots, restore drill workflow, and the monitoring that tells you when it stops working.
- [BIMI with VMC — Cost, Process, and Whether It's Worth It](https://acellesend.com/kb/articles/bimi-with-vmc-cost-walkthrough): VMC (Verified Mark Certificate) costs $1,500/yr per domain and takes 4-8 weeks to obtain. This guide walks the cost math, the trademark requirements, the alternative paths, and a decision framework for whether VMC is right for your sending program.
- [Building Your Email Marketing SaaS](https://acellesend.com/kb/articles/building-your-email-marketing-saas): The technology side of an AcelleMail SaaS is solved. The hard part is the business: who you sell to, how you price, how you reach them, and how you keep them. This guide is the GTM + pricing playbook — opinionated, market-tested patterns for launching an email-marketing SaaS on the AcelleMail stack.
