I did not want the first version of the DAM to depend on a message broker.
It needed to ingest large batches of photography reliably, survive interruption, and make its current state obvious when something went wrong. For one operator on a local network, adding a database and queue service would have created more infrastructure than the workflow justified.
Four directories were enough.
Location Is State
Each ingest request is represented by a job file. Its directory tells the system what state it is in:
_jobs/
queued/
running/
done/
failed/
The web interface creates a job in queued. A worker claims it by moving it to running. Success moves it to done; an exception moves it to failed with diagnostic information.
There is no separate status row that can disagree with the filesystem. Inspecting the queue requires no administrative console. Recovery can be as direct as reading a file, correcting the cause, and deliberately returning a failed job to the queue.
Simple Does Not Mean Casual
A filesystem queue still needs rules.
Claims must be atomic so two workers cannot process the same job. Job files need stable identifiers and validated inputs. A partially completed ingest must be safe to run again. Logs and manifests must preserve enough information to understand what happened.
The larger ingest design helps here. Inventory is read-only. Identity is based on hashes. Originals become immutable only after commit. Repeating earlier phases should not create new identities for the same files.
The queue is simple because the workflow around it is disciplined.
The Database Can Arrive Later
A database becomes valuable when there are multiple users, complex searches, reporting requirements, or enough concurrent work that filesystem polling becomes inefficient.
None of those conditions existed at the start. Adding PostgreSQL early would not have made the original photographs safer. It would have introduced another service, another backup concern, and another state model.
The DAM’s broader rule is that files are authoritative and databases are rebuildable indexes. The queue follows the same philosophy: represent operational truth in a form that remains inspectable even when the application is down.
There is a ceiling to this approach. That is acceptable. Good small-system design is not pretending scale will never arrive; it is refusing to pay for scale before it has a job to do.