API Reference
API Reference
GitHub
Getting Started

Splitting the roles

Run the API and the delivery worker as separate nodes

serve runs both halves in one process, and several serve nodes against one database already share the queue exactly as described in Scaling out . What is on this page is running the two halves on separate MACHINES, not the ability to run more than one node.

The three commands

CommandHTTPSMTP listenersDelivery queueCampaignsMaintenance jobs
mailyard servefullyesyesyesyes
mailyard apifullyesnonono
mailyard workerprobes onlynoyesyesyes

mailyard sender is an alias for mailyard worker.

A role is a subcommand rather than a config key on purpose. The point of splitting roles is to put more machines behind one queue, and a config key would mean every one of those machines needs its own config file differing in a single line. Instead every node ships the same ../../../mailyard.yaml (or the same MAILYARD_* environment) and the role is a word in argv, which is already per-container in every orchestrator.

services:
    api:
        image: mailyard:latest
        command: [ "api" ]
        env_file: mailyard.env
        ports: [ "3000:3000" ]

    worker:
        image: mailyard:latest
        command: [ "worker" ]
        env_file: mailyard.env
        deploy:
            replicas: 3

Add worker replicas freely. There is no leader, no registration and no partitioning to configure - a worker that starts simply begins claiming.

What each role does

api accepts mail and hands it to the database. POST /api/v1/emails/send, the console, the tracking endpoints, the SMTP relay and the inbound MX listener all live here. It never delivers anything.

worker drains the queue, runs campaigns, and performs the scheduled sweeps (retention-cleanup, bounce-alert). It binds server.addr but serves only /healthz, /readyz and /metrics - enough for an orchestrator probe and a Prometheus scrape, without putting the console on a machine that has no reason to expose it.

Note the consequence: an api-only deployment never sends anything. Mail piles up in the queue with status queued until a worker exists.

The settings-refresh job runs on every role, including api. It is not maintenance - it is how a node’s settings cache learns about a change written on another node.