DEV Community

Cover image for Products, 2 GB of RAM, and One Rule: The Filesystem Is the Database**

Products, 2 GB of RAM, and One Rule: The Filesystem Is the Database**

Products, 2 GB of RAM, and One Rule: The Filesystem Is the Database

I lost track of which files were already posted.

It was a plain text file. posted.txt. It started accurate. Then I ran a batch, the script crashed halfway, I restarted it, and about 200 rows went up a second time. Only a warning that time, no suspension, but I understood the shape of the problem: the thing that fails on a stock channel is not bad art. It is running the same batch twice.

That was the day I stopped treating the filesystem as storage and started treating it as the database.

The filesystem is the database

There is no Postgres in this pipeline. There is a folder of files and one rule: the filename, plus a state file, is the source of truth for everything.

Every asset gets one name. Every name lives in exactly one ledger. upload_tracker.py reads that ledger and answers one question per file: done or not done.

python upload_tracker.py pending items.txt   # shows what is NOT done yet
python upload_tracker.py done "asset-001.jpg"
python upload_tracker.py status
Enter fullscreen mode Exit fullscreen mode

A re-run can only ever pick up the leftovers. Double-posting is not a discipline problem any more, it is structurally impossible.

The layout that keeps this sane:

project/
  assets/      raw output, one file per asset
  output/      ready-to-submit files + metadata.csv
  packs/       finished product zips + covers
  research/    notes and sources
  scripts/     the tools
Enter fullscreen mode Exit fullscreen mode

I deleted research/ once, to "clean up". Those scrape logs and notes were the raw material for the next two products. They are gone. Keep that folder forever.

The headers are the review

I made 1,700 assets before I understood that most rejections never reach a human. They are CSV validation.

Three channels, three shapes, all strict:

  • Adobe: 5-column metadata CSV
  • Vecteezy: 4-column
  • Dreamstime: 15-column

Wrong header, wrong column count, wrong order, and the whole file bounces instantly. No partial import. You do not get file 1 through 40 and an error at 41. You get nothing.

So make_metadata.py writes the header the platform demands and nothing else:

python make_metadata.py ./my-assets --platform adobe      --out metadata.csv   --ext .jpg
python make_metadata.py ./my-assets --platform vecteezy   --out vecteezy.csv   --ext .jpg
python make_metadata.py ./my-assets --platform dreamstime --out dreamstime.csv --ext .jpg
Enter fullscreen mode Exit fullscreen mode

Two of my four scripts use the standard library alone. No install, no dependency, no version drift. make_metadata.py and upload_tracker.py need nothing but Python. Only pack_product.py needs Pillow and only md2pdf.py needs reportlab.

Pass --titles titles.json when you have real titles and keywords. Without it the script title-cases the filename and uses that. That is a first pass, not a submission.

1 vCPU, 2 GB RAM, no GPU

This whole pipeline ran on a single core with 2 GB. Not as a stunt. Because that is what a $5 box gives you and the work fits.

Four habits made it fit:

  • One process at a time. Never fan out image jobs on one core. Parallel work on 1 vCPU does not finish faster, it just swaps.
  • Free memory between items. gc.collect() after each asset. Boring, and it keeps the RSS flat across a 500-item run.
  • Measure peak RSS, not average. resource.getrusage(RUSAGE_SELF).ru_maxrss gives you the real ceiling. Average memory tells you nothing about the item that killed the process.
  • One file per subprocess for heavy renders, so memory returns to the OS instead of sitting in the parent.
  • Render at the resolution you need. Checking a preview at 60 dpi does the job. Rendering it at 300 dpi to look at it wastes the box.

This matters because every generated image costs money. A process that dies at item 200 of 500 does not just waste an hour, it wastes the spend on those 200 items.

Packaging is half the product

A zip with a real cover sells. A bare file does not.

python pack_product.py my-product "My Product" "A short subtitle" 9
Enter fullscreen mode Exit fullscreen mode

That one command writes the zip, a 1280x720 cover, and a 600x600 thumbnail into _system. If you want it somewhere else, use --dir or the PACK_ROOT environment variable. No reason to edit the script for a path.

md2pdf.py does the same job for written products:

python md2pdf.py content.md product.pdf "My Product Title"
Enter fullscreen mode Exit fullscreen mode

Headings, tables, lists, links, styled. Content you already wrote becomes a thing with a cover and a price.

Where it actually stands

Real numbers, because the honest ones are more useful than the round ones:

  • 1,700 assets made
  • 58 live on Adobe
  • first sale: $0.99

That is the whole scoreboard. 58 live out of 1,700 generated is the part nobody puts in a post. Review is slow, keywords matter more than volume, and one sale at $0.99 will not pay for anything.

What made the difference was not art quality. It was that the pipeline stopped wasting its own output. Nothing double-posted, nothing silently dropped, nothing lost to a crash on a 2 GB box.

The kit

The four scripts above are the packaging layer of a larger system. In the full pipeline they sit under a free stack: an orchestrator that schedules jobs and retries failures, and a local proxy for model access, both at zero cost. The parent project is around 19,000 lines and sits on top of 300+ pages of research notes, most of which exist because a platform rejected something and I had to find out why.

I put the working parts into digital asset factory, the full system built from this work. Not a tutorial that ends at "here is how you would do it". The scripts run, the headers are the ones the platforms accept, and the RAM notes come from a box that really did have 2 GB.

If you only take one thing: stop trusting your memory of what you posted. Put it in a file, and let the file decide.

Get digital asset factory


Building digital products? Free guides & kits for digital product sellers.

Top comments (0)