Inspiration

Old apps keep running because switching them off could lose records or expose private files. Low traffic doesn't mean nobody needs the data. Keeping everything running forever costs money and upkeep. Owners need a safe way to say "this can go" and prove nothing important went with it.

What it does

The owner first fixes the requirements: which records must survive, who may see what, and how long to keep it. Then:

  1. GitLab Duo decides RETIRE, KEEP or SCALE DOWN for each app, against those requirements. Low traffic alone is never a reason to retire. Duo also lists the conditions that must be met before anything is deleted.
  2. Trusted code proves the data survives. It switches the app to read-only, archives it, restores it into a fresh PostgreSQL database, and checks the records, attachments and access rules.
  3. One person approves the exact plan: the archive, the snapshot and the resources to remove.
  4. The controller acts. It switches the front door to the preserved read-only service, checks access, removes only the approved old container and its volume, then checks access again. Running it a second time does nothing.

It's for teams that need to shut down old systems without losing records or breaking privacy rules.

Duo's conditions controlled the deletion

Duo's condition before retiring What the record shows
Archive reconciliation must pass Met
Fresh restore must verify records and attachments Met: 8 tables, 3 attachment hashes
Access checks for anonymous, reader and admin Met: 18 of 18
Writes fenced before cutover Met
Owner approval of the exact plan Met, before any effect
Environmental benefit Not established. No claim.

Duo also made the right calls on the other two apps: KEEP the one still taking enrolments, and SCALE DOWN the one needed live this quarter.

Try it yourself

Live on Google Cloud

The preserved read-only app that replaced the retired one is live on Google Cloud Run: https://lights-out-preserved-918290555848.us-central1.run.app The page lists ready-made requests: a reader is refused a private file (403), an admin can read it (200), and writes are refused (409). It was deployed after the recorded local retirement, from the same verified archive. Fictional data; the demo tokens are public.

How we built it

  • Python (standard library) and PostgreSQL 16.6 for the app, archive, restore and read-only replacement.
  • GitLab Duo Agent Platform for the decisions and the preservation plan. Duo returned decisions only; it wrote no code.
  • GitLab CI restores the exact archive in a fresh PostgreSQL and runs the access checks on the merge request (Draft MR !2).
  • SQLite holds the controller's record, so a repeated run can't repeat its effects.

Challenges

The first attempt passed CI but stopped before approval, when GitLab refused a job-detail request. Nothing was deleted, and its temporary resources were cleaned up. After a reviewed fix, the recovery reused the same Duo response with a fresh archive, MR, CI and approval. It's on the record as a recovery, not a first-try success.

Accomplishments we're proud of

  • Proof that the data and the access rules survive, checked before anything is deleted.
  • Refusals that work: KEEP when writes are still needed, refusal if the plan changes after approval, and no repeat effects.
  • One human decision, tied to an exact plan, instead of many small approvals.

What we learned

A backup file isn't preservation. Relationships, attachments, permissions, a fresh restore and an exact approval all matter. The useful line for an agent is between proposing and acting.

Limits (honest)

  • A local, disposable fixture app. Not a production or cloud retirement.
  • The approval was local operator consent tied to the exact plan, not a GitLab MR approval. The MR stays Draft and unmerged.
  • The Duo session page needs a GitLab sign-in. Duo's response is copied publicly into the repo.
  • Environmental measurements were mixed, so no energy or carbon saving is claimed.

What's next

Cloud adapters, approval inside GitLab (protected environments), and independent signing for the approval record.

Links

Built With

Share this project:

Updates

Submission history