← All writing
architectureawscostoperations

Keeping a Family Archive Small Enough to Operate

How storage cost, deletion semantics, mobile limits, and observability shape a private archive without requiring a larger platform.

A family archive should remain understandable after the initial enthusiasm of building it has passed.

That is an operational constraint. I need to know where the bytes live, what a deletion means, which failures need attention and which expenses grow with usage.

Managed services help reduce the amount of infrastructure I maintain. They do not remove these questions.

Cost begins with access patterns

The implementation separates originals from previews. Browsing uses small derived images, while original downloads are explicit operations.

That separation affects both bandwidth and future storage policy. Frequently used previews and rarely opened older originals need not have the same treatment forever.

However, the current Terraform configuration does not transition completed originals to a colder storage class. The lifecycle rule currently implemented is for incomplete multipart uploads.

I want that distinction to be visible. A plausible future optimization is not a shipped cost saving.

Before adding a colder tier, I would need to understand actual access frequency, object sizes, retrieval requirements and the current pricing rules. A family member opening an old video should encounter an intentional product decision if retrieval becomes delayed.

There is no useful universal monthly estimate

The architecture gives me a cost model rather than a defensible fixed bill:

Storage
  originals + previews + incomplete parts

Requests and compute
  API + catalogue operations + queue + preview processing

Transfer
  browsing + original downloads

Operations
  logs + alarms + recovery features

DynamoDB uses on-demand billing. Lambda and SQS support work that arrives intermittently without requiring an application server to run continuously.

These are sensible mechanisms for the current workload. They do not demonstrate that this solution is cheaper than every subscription service. That would require measured usage and a comparison with the products the family actually needs.

Bounded work protects the phone too

Server cost is only part of the budget. Preparing a transfer requires reading an original, copying it into application storage and hashing it. Videos also require preview images.

Automatic backup therefore discovers metadata in pages and prepares only a small number of transfers. Two queue slots bound automatic preparation, and the native transfer queue also limits concurrency.

The working copy makes recovery less dependent on the photo library at the moment of transfer. It consumes extra local storage in exchange.

That exchange deserves attention when the user has a large library or little free space. A persistent queue cannot make unavailable disk capacity disappear.

Deletion is a distributed operation

Removing a cloud item involves catalogue state, originals, previews and potentially an upload that is still in flight.

The mobile application persists deletion intent and hides the item locally. It can replay the request when connectivity returns. Local deletion markers prevent an older catalogue response from immediately restoring the item to the screen.

The backend marks the media as deleting, removes stored objects and then removes the media record. The worker checks for concurrent deletion around preview creation. Late original-creation events for missing or deleting media trigger cleanup.

This is an eventual cleanup process. A previously issued URL or an in-flight operation can outlive the UI action briefly; deletion is not instantaneous revocation of every outstanding capability.

The cloud deletion does not delete the photo from the phone’s library.

Recovery data can intentionally survive deletion

S3 versioning is disabled in this design so deleting an original does not leave an older object version retained by versioning.

The backend does retain small request records after media deletion. Replaying an old initiation request must not resurrect the deleted media. The content reservation is removed with the media so a genuinely new operation can have a different outcome.

This is a useful example of retention following meaning: original bytes and an idempotency record have different jobs.

Disabling versioning also removes one recovery mechanism for accidental object deletion. Calling the application a vault does not establish immutable retention, an independent second copy, or a tested disaster-recovery process. Those require their own requirements and verification.

Observe the workflow rather than only the process

Infrastructure alarms cover API failures, Lambda errors and duration, queue age and dead-letter queue activity.

Preview processing needs an additional signal. With partial batch responses, the Lambda invocation can return successfully while reporting failed messages. A process-level error count alone would miss that business failure. Structured worker error logs supply another alarm input.

For users, persistent waiting reasons explain conditions such as missing permission, Wi-Fi policy or occupied transfer slots. An inactive transfer screen has several possible causes; the UI should expose the relevant phase instead of presenting them all as silence.

Logs exclude JWTs, signed URLs and photo contents. Investigating a workflow should not create another uncontrolled copy of the archive.

Keep the boundaries explicit

The current design has account isolation, direct authorized storage transfers, durable local work, bounded preparation, multipart recovery and asynchronous previews.

It remains subject to mobile operating-system scheduling. It does not implement end-to-end encryption, cross-account family sharing, immutable archival retention or verified recovery from loss of the entire storage environment.

Those are possible future requirements. Each would justify new mechanisms and new costs.

The architecture stays manageable when those decisions are made explicitly: a concrete constraint, a mechanism that addresses it, and an honest account of the work that remains.

Thanks for reading.Back to the notebook →