# Apiway generation worker (Docker microservice) > Heavy templates (`ghost-mannequin`, `ai-photoshoots`) are offloaded to a Docker microservice on the apiway server (185.18.52.178, 64GB RAM, 10 worker containers). This file explains the contract — environment toggle, table-based queue, S3 storage, rollback path. Source of truth: `generation-worker/` (excluded from Next.js tsconfig), `docs/GENERATION_WORKER_SETUP.md`. ## Why offload Heavy templates run subject segmentation, alpha matting, post-processing pipelines (e.g. white-studio recomposite), and Gemini calls in series. On Render's web tier these block the event loop, monopolize the heavy queue, and tank latency for everyone else. The worker pool absorbs them. ## Toggle The `OFFLOAD_TEMPLATES` env var on Render is a comma-separated list of template ids. If a generation request matches, it goes through the queue: ``` OFFLOAD_TEMPLATES=ghost-mannequin,ai-photoshoots ``` To **roll back** the worker entirely, remove the env var. Everything goes back to in-process Render execution. No code change needed. ## Communication: Supabase table, not HTTP Next.js and the worker do not talk over HTTP. They share a Postgres table: ```sql CREATE TABLE generation_jobs ( id uuid PRIMARY KEY, user_id uuid NOT NULL, template_id text NOT NULL, status text NOT NULL, -- 'queued' | 'running' | 'done' | 'failed' payload jsonb NOT NULL, -- request input result jsonb, -- output { gallery_image_ids, ... } error text, created_at timestamptz, started_at timestamptz, finished_at timestamptz ); ``` Flow: 1. Next.js route inserts a row with `status='queued'` and the input payload. 2. Worker container polls for `queued` rows it can claim, sets `status='running'`, and processes. 3. On success: writes images to S3 (`apiwayimages`, eu-north-1), inserts `gallery_images` rows with `storage_provider='s3'`, sets `status='done'` and `result` JSON. 4. On failure: sets `status='failed'` with `error`, calls `try_refund_credits()` to give the user back their balance. 5. The Next.js client polls the row by id (or subscribes via Supabase Realtime) and renders the result. ## Storage: AWS S3 `apiwayimages` - Bucket: `apiwayimages` - Region: `eu-north-1` - Access: presigned GET URL on read (`getSignedUrl` from `@aws-sdk/s3-request-presigner`, expires 5 min) - Credentials: `APIWAY_AWS_ACCESS_KEY_ID` / `APIWAY_AWS_SECRET_ACCESS_KEY` env vars on both Render and the worker host ## Build separation `generation-worker/` is **excluded from the Next.js build**: - Listed in the Next.js `tsconfig.json` `exclude` array. - Has its own `tsconfig.json` and `package.json`. - Builds independently as a Docker image. - Uses the Supabase admin (service-role) client because it writes across users. If you accidentally import worker code from a Next.js file, the build will pull the whole worker tree in and fail with weird module errors. Keep the boundary clean. ## Heavy queue rate limits (in-process fallback path) Even with `OFFLOAD_TEMPLATES` set, the in-process path still exists for rollback. Heavy templates there are gated: - One heavy job per server process at a time. - /api/generate rate-limited to 60 req/user/min. - 503 with a 30-second retry hint when the heavy slot is busy. See `docs/GENERATION_WORKER_SETUP.md` for full deploy instructions, and `docs/UNDERSTANDING_THE_PROJECT.md` for the architecture diagram. ## Common bugs - Adding a new template id to `OFFLOAD_TEMPLATES` without updating the worker → jobs queued forever. - Forgetting to set AWS env vars on the worker → S3 writes fail, status stays `queued`. - Using user-scoped Supabase client in worker → RLS blocks cross-user writes; must use service role. - Importing from `generation-worker/` in Next.js code → build pollution. ## Cross-references - Setup guide: `docs/GENERATION_WORKER_SETUP.md` (in repo) - Templates this affects: https://localhost:10000/llms/ghost-mannequin.txt, https://localhost:10000/llms/ai-photoshoots.txt - Heavy queue troubleshooting: https://localhost:10000/docs/troubleshooting/heavy-queue-busy - Storage architecture: https://localhost:10000/llms/gallery-storage.txt --- *Generated on 2026-05-01. Source: `generation-worker/`, `docs/GENERATION_WORKER_SETUP.md`, `docs/UNDERSTANDING_THE_PROJECT.md`.*