A product image cleaner on AWS for a few dollars a month
A small shop takes its own product photos, and they all start the same way: a phone snapshot on a counter or a windowsill, good enough to see the thing but nowhere near ready for a web store or a marketplace listing. Cleaning each one up by hand — cut out the background, square it off, resize it three ways, drop the logo on — is ten fiddly minutes per product that nobody enjoys. This post walks through the design of a small system that does all of it the moment a photo lands, and hands back doubtful ones instead of shipping them.
Key takeaways
- You drop a raw phone photo into a folder; it lands in S3, and the upload event itself starts the whole pipeline.
- Background removal runs in a container-image Lambda on arm64 with extra memory — the one heavy step, kept apart from the rest.
- Cropping, resizing, compositing onto white, and watermarking are plain deterministic image ops in Pillow.
- One photo becomes a full set of channel variants — web store, marketplace square, social — written back to S3 ready to use.
- Designed on AWS for about $3.40/month at roughly 400 images. A doubtful cutout is held for review, never published.
The whole system on one page
Before any code, here’s the shape of what we’re designing. A small shop takes its own product photos, and every one of them starts the same way: a snapshot on a phone, taken on a counter or against whatever wall was nearest. It’s enough to see the product, and nowhere near ready to put on a web store, an Amazon listing, or an Instagram grid. The gap between “photo I took” and “image I can publish” is ten fiddly minutes of cutting out the background, squaring it off, resizing it three different ways, and dropping the logo on. The system below closes that gap automatically, and does nothing else.
What you set up once (the outside)
- Raw photos. A folder you drop snapshots into — a Google Drive folder that mirrors into an S3
inbox/prefix, or theinbox/prefix itself through a simple upload link — plus an email lane for the times you’d rather just send a photo from your phone. Whichever lane a file comes in on, it ends up as one object ininbox/, and that single fact — an object appearing — is what starts everything. This is Part 2. - Brand and channel rules. One short config you set once: your logo as a transparent PNG for watermarking, and the exact spec for each channel — pixel dimensions, background (transparent, or pure white), how much padding to leave around the product, and whether a watermark is allowed. A typical set is a 1600×1600 web-store image, a 2000×2000 white marketplace square, and a 1080×1080 social square. The marketplace variant carries no watermark on purpose, because the big marketplaces reject main images that do.
- Where they land. The places the finished images go and the person who uses them. The cleaner writes each variant back to S3 under a per-channel prefix and sends one notification — “Candle no. 4: 3 images ready” — with links. It never logs into your store or your marketplace account and never publishes a listing; it produces files and tells you they’re ready. You stay in charge of what actually goes live.
What runs on every photo (the inside)
- Ingest. The photo lands in
inbox/and the S3 upload event fires. A small Lambda checks the file really is an image, fixes the things phones get wrong — reads the EXIF rotation and turns the picture the right way up, converts HEIC to a workable format, caps the longest edge so a 12-megapixel snap doesn’t cost more than it needs to — and opens a job row. This is Part 2. - Cutout. The one heavy step, and the only place a model runs. A container-image Lambda on arm64 with extra memory runs a segmentation model (rembg with U^2-Net, or a hosted vision model) that decides, pixel by pixel, what is product and what is background, and composites the product onto transparency. It also scores the result — how much of the frame the product fills, how clean the edges are — so a bad cutout can be caught here. This is Part 3.
- Variants. With a clean cutout in hand, plain Pillow operations do the rest: trim to the product, pad it to the channel’s safe area, resize to the exact pixel size, composite onto white where the channel wants white, and stamp a subtle watermark where it’s allowed. No model is involved — it’s deterministic arithmetic, so the same cutout always yields the same set. This is Part 4.
- Publish. The finished variants are written back to S3 under
out/web/,out/market/, andout/social/, a manifest records exactly what was produced, and the owner gets a single notification. The original is never touched. This is Part 5.
In plain words
A homeware shop adds a new candle to the range. The owner stands it on the kitchen counter, takes one photo on her phone — 4,032×3,024 pixels, the toaster just visible behind it — and drops it in the Drive folder. Seconds later the upload event has fired, the container Lambda has lifted the candle cleanly off the counter, and the variant step has produced three files: a 1600×1600 web image of the candle floating on white, a 2,000-pixel marketplace square with the product filling most of the frame and no watermark, and a 1080×1080 social square with the shop’s logo faint in the corner. Her phone buzzes: “Sea Salt candle: 3 images ready.” The whole thing took less time than it took her to put the kettle on.
The next photo is a clear glass vase, and the cutout comes back doubtful — the model has eaten away the see-through middle, leaving a ring. The cleaner doesn’t build anything from it. The job stops at needs review and she gets the original and the attempted cutout side by side, so she can reshoot the vase against a plain backdrop rather than discover the hole after it’s live on three channels.
Design rules that shaped every decision
- The upload is the trigger. A file appearing in S3 starts the pipeline; there’s no button to press and nothing to poll.
- One heavy step, kept apart. Only background removal needs a big container and a model; everything else is small and cheap.
- The model produces a mask, nothing more. Cropping, sizing, and watermarking are deterministic image arithmetic.
- It changes pixels, it doesn’t describe them. This is a cleaner, not a tagger — there is no caption and no metadata guesswork.
- A doubtful cutout is held, never shipped. Low-confidence results stop at review with the original attached.
- The original is sacred. Every variant is a new object; nothing overwrites the photo you dropped in.
Why this shape
Most small shops handle product photos one of three ways: they pay a studio (slow and expensive for a changing range), they wrestle each shot through a desktop editor by hand (ten minutes a product, and the results drift as whoever’s doing it gets bored), or they post the raw snapshot and hope (which is why so many small listings have a kitchen counter in shot). The first doesn’t scale to a shop that adds products weekly. The second is the dull, repetitive work that always slips. The third quietly costs sales, because a cluttered photo reads as a cluttered business.
The shape above takes the one snapshot you were always going to take and turns it into the full, consistent set the moment it lands — the same crop, the same backgrounds, the same watermark rule every single time. The heavy bit is isolated in its own container so the rest of the system stays small and almost free. And because a bad cutout is caught and handed back rather than published, the failure mode is “reshoot this one,” not “a vase with a hole in it is now live on Amazon.”
The next four posts walk through each piece in turn: how a raw photo gets ingested, how a background gets removed, how the channel variants get made, and how a cleaned image gets published. One diagram per post. A cost breakdown and a final engineering reference at the end.
All posts