You need two thousand product shots by Friday, or you're backfilling an entire catalog, or you're stress-testing a client pipeline. Whatever the reason, you've hit the wall every heavy user hits: pasting 1000+ prompts into Discord one at a time is not a plan, and a for loop that fires 1000 requests at once is a plan that fails around image #75.
The core fact first: midjourney bulk generation is a queue problem, not a loop problem. Midjourney has no official public API — everything automated runs through Discord accounts with rate limits, sessions that expire, and failures that happen silently. A modern image takes 30-60 seconds to generate, which means a thousand images is four to eight hours of continuous pipeline time at best. The only question is whether that pipeline survives all four hours without you watching it.
Nextjourney is not affiliated with Midjourney or Discord. There is no official API, as covered in our explainer on whether Midjourney has an API — bulk automation operates through Discord user accounts, which sits outside Discord's Terms of Service. That risk applies to every approach below equally; it's something to engineer around, not a reason to stop.
What breaks when you loop midjourney bulk generation naively
If you've ever written the obvious version — a script that submits a prompt, waits, downloads the result, repeats — you know it works for the first dozen images. Then three things happen in sequence:
- Rate limits. Midjourney throttles how fast one account can submit. Fire 1000 jobs at a single connection and most of them will sit in a waiting state or get rejected. The errors are often silent: your request "succeeds" at the Discord layer and the actual generation never starts.
- Silent failures. Upscales fail, prompts get rejected by the bot, sessions expire mid-batch. A naive loop treats "no image after 60 seconds" as a hang, retries blindly, and multiplies the load on the exact account that's already failing.
- No checkpointing. Your script dies at image 847 — network blip, server restart, laptop lid closed — and you restart from zero. At 30-60 seconds per image, restarting from zero is not a small cost.
These are the reasons "just loop it" advice stops being useful around image #100, and why every serious implementation looks like the pipeline below.
The pipeline that processes 1000+ images
Five layers, same shape as our full guide to automating Midjourney, tuned here for high-volume runs:
A job queue. Every prompt enters a queue the instant it's submitted. Nothing talks to Discord from your request path. The queue absorbs bursts, lets you pause, and gives you a single source of truth for "what's left to do." The full state machine behind it — persistence, idempotency, retry semantics — is covered in the ai image generation architecture deep dive.
Per-account concurrency caps. Workers pull jobs from the queue, but each Discord account gets a hard concurrency cap — usually 1-2 concurrent jobs. More accounts, not more parallelism per account, is how throughput grows. Account rotation and rate-limit behavior are covered in depth in our Midjourney account safety guide.
Retry with backoff. Transient failures (rate limit, timeout) re-enter the queue with exponential backoff. Permanent failures (bad prompt, dead session) are marked failed and reported. Blind retries just multiply the load on a limping account.
Checkpoint/resume. Persist job state after every completion. If the process dies, it resumes from the last checkpoint instead of restarting the whole batch.
Webhooks or a status API for results. Your batch runner doesn't poll aggressively; it gets told when a job completes. For a one-off bulk run you can poll gently, but the job model stays the same.
Here's a minimal Node.js runner that demonstrates the shape — queue, per-account cap, retry with backoff, checkpoint file:
// bulk-runner.js — the shape, not the full implementation
import { readFile, writeFile } from "node:fs/promises";
const JOBS = [ /* 2000 prompts */ ];
const ACCOUNTS = [{ id: "acct-1", concurrency: 1 }, { id: "acct-2", concurrency: 1 }];
const CHECKPOINT = "bulk-checkpoint.json";
async function loadCheckpoint() {
try { return JSON.parse(await readFile(CHECKPOINT, "utf8")); }
catch { return { done: [], failed: [] }; }
}
async function submitWithRetry(prompt, account, attempts = 0) {
try {
return await submitAndWait(prompt, account); // POST /jobs, poll status, fetch image
} catch (err) {
if (err.type === "rate_limited" && attempts < 5) {
await sleep(2 ** attempts * 5000); // exponential backoff
return submitWithRetry(prompt, account, attempts + 1);
}
if (err.type === "session_expired") { account.reauth(); }
throw err;
}
}
const state = await loadCheckpoint();
let cursor = state.done.length + state.failed.length;
while (cursor < JOBS.length) {
const account = ACCOUNTS.find(a => a.running < a.concurrency);
if (!account) { await sleep(1000); continue; }
account.running++;
JOBS[cursor] // submit with the next free account
.then(job => submitWithRetry(job.prompt, account))
.then(image => state.done.push({ prompt: job.prompt, image }))
.catch(err => state.failed.push({ prompt: job.prompt, error: String(err) }))
.finally(() => { account.running--; cursor++; });
await writeFile(CHECKPOINT, JSON.stringify(state)); // checkpoint after every job
}
The point isn't this exact code — it's the three properties: nothing is thrown away, nothing is retried blindly, and a crash at image 847 resumes at image 847. The full submit/poll/error surface is documented in our Midjourney REST API guide, and the Python equivalent follows the same pattern in our Midjourney API with Python tutorial.
Throughput math: what 1000+ images really costs
Numbers matter more than vibes here, so let's do the arithmetic with honest assumptions (generation around 45s per image, one job per account at a time):
| Config | Images / hour | 1000 images |
|---|---|---|
| 1 account, 1 concurrent job | ~80 | ~12.5 hours |
| 2 accounts, 1 concurrent job each | ~160 | ~6+ hours |
| 4 accounts, 1 concurrent job each | ~320 | ~3+ hours |
| 8 accounts, 1 concurrent job each | ~640 | ~1.5-2 hours |
These are estimates — real throughput depends on Midjourney's current GPU tier, job type (standard generations vs upscales vs variations), and how the platform queues work during peak hours. Plan for the conservative column and you'll be pleasantly surprised.
The cost side is where bulk gets interesting. At 1000+ images a month you're past what a single paid subscription tier comfortably covers. Our Midjourney API pricing breakdown walks through the per-image math, and the cheapest way to use Midjourney at scale compares the three ownership models head to head. The short version: renting per-image API access scales linearly and painfully, while a self-hosted platform — full source code, backend, REST API, admin dashboard — removes the per-image meter entirely. One license instead of a monthly bill that grows with every batch.
Run one batch, or build the capability
If this is a one-off job, the runner above plus honest throughput expectations gets you to a thousand images. If this is a recurring capability — a client service, a content pipeline, a product feature — build the queue layer once and stop thinking about per-batch scripts. That's the difference between bulk generation as a hack and bulk generation as infrastructure, and it's exactly what the platform we license exists for.
Ready to self-host?
Full source code — backend, frontend, REST API, admin dashboard. Queue, workers, retries, and account rotation handled for you. One-time license from $399, no per-image fees.
See pricingQueue everything, cap concurrency per account, retry with backoff, checkpoint relentlessly. Four decisions, and you'll process 1000+ images on a long lunch break instead of a week of babysitting.
Not affiliated with Midjourney or Discord.