Design, style prompts, marketing and user acquisition — on the side of the publisher, Evrika Games; another developer finished the payments and subscriptions integration
Challenge
A mobile app for AI photo shoots with its own image-processing system: from uploading photos to a finished series of pictures and videos in the chosen style.
The path of one order
A generation takes one to ten minutes — longer than an HTTP request lives. So an order goes through a queue and its own workflow: a crashed worker or a dropped connection does not lose the result.
APPFlutter client
Recompresses the photo — usually under 1 MB — and uploads it over tus, resuming after a dropped connection. A photo uploaded before is recognised by its hash and not sent again.
APINestJS API
Checks the preset and the coin balance, stores the order in PostgreSQL and queues a job keyed by the order id.
QUEUEBullMQ on Redis
Workers take jobs from the queue; a stalled job is handed to another worker.
WORKFLOWbull-dozer
The order's steps: generation on Replicate, for video — waiting for the model and ffmpeg processing, then the watermark. Each step has its own retries.
CDNS3 and CloudFront
The original, a thumbnail and a watermarked copy. Signed cookies open only the files of the user's own profile.
RESULTBack to the app
The server publishes the status to the user's Redis channel; the client waits for it with a long-polling request of up to 60 seconds.
A worker crash is never paid for twice
bull-dozer stores every step's result in Redis. A restarted workflow replays finished steps from the cache and does not call the paid model again; raw video is saved to S3 before the Replicate link expires.
The result arrives the moment it is ready
Long-polling on top of Redis pub/sub: the client learns about completion at once, without timer polling and without separate push infrastructure.
A pipeline on Replicate: order queue, multi-stage generation, video in several scenarios, joint generations, post-processing, watermarks, retries.
bull-dozer: a NestJS module for deterministic orchestration of long-running workflows on top of BullMQ, Temporal-style — replay, step cache, nested steps, retries, timeouts. Open source, MIT.
Distributed NestJS services and workers on Redis / BullMQ, PostgreSQL, payment processing, monitoring.
AWS: ECS and ELB, S3 and CloudFront, DynamoDB, Secrets Manager; separate environments.
React admin panel: orders, users, stories, promo codes, configs imported from Google Sheets, a test-generation builder that follows the pipeline stages.
15 GitHub Actions CI pipelines for the client, server, workers and infrastructure; automated tests and DB migrations.
Outcome
~114K lines of production code in four parts, 12 App Store versions, ~6.5K generations with a 54-second median.
Together with the publisher we tested paid acquisition: the traffic did not pay off, so development was stopped.