Memento Mori: Building a Deadman Switch

Cover Image for Memento Mori: Building a Deadman Switch
Nathan Tang
Nathan Tang
8 minutes
Active
Last check-in: March 9, 2026 at 10:02 AM

Table of Contents

The Palm Reading

Last year, an ex read my palm. Her grandma taught her — it's a party trick of hers. She traced a line across my hand, paused, and told me I'd die young.

I laughed. She didn't.

I'm actually a big fan of astrology — I built a whole fusion system around it. Can I prove any of it actually means anything? No. But I won't shame anyone for believing in it either. Palm reading though, telling someone they're going to die young — that's a different vibe. There's something about hearing someone you care about say that to you, even casually, that just sticks. Not as fear exactly — more like a low-frequency hum in the background of your decision-making that you don't notice until you do.

I started thinking about the boring version of dying. Not the dramatic movie version where everyone gathers and there's a whole thing. The version where your Spotify keeps playing Discover Weekly to nobody, your recurring emails keep sending, your landlord eventually notices. Who would know? How fast? Which things would just quietly fall through the cracks?

There's also the practical angle — my parents live on the other side of the country, and this gives them one more way to know I'm okay. They don't need to check the widget or anything, but knowing the system exists is its own kind of reassurance.

Anyway, that's the headspace I was in when I decided to build a deadman switch. Totally normal behavior.

What's a Deadman Switch?

The concept comes from trains. Old locomotives had a physical lever the engineer had to hold down while the train was moving. If they let go — fell asleep, had a medical emergency, or worse — the switch would activate and stop the train. There's something kind of beautiful about a machine that interprets silence as a problem.

A digital deadman switch is the same idea: you check in periodically to prove you're still around. If you stop checking in, the system assumes something went wrong and takes action.

I know this sounds morbid. It is, a little. But it's also just practical. Everyone has messages they'd want sent, things they'd want people to have access to. A deadman switch is the infrastructure for handling all of that. It's the difference between "I should really write a will at some point" and actually doing something about it, except it also covers the case where nobody knows to go look for the will in the first place.

I think the reason most people don't do this stuff isn't that they're scared of death. It's that the logistics are boring and depressing and it's a Saturday afternoon and there's a new season of whatever on Netflix. Which is fair, honestly.

How It Works

The system is a state machine with escalating tiers. I check in periodically (there's a shortcut on my phone — one tap). As long as I keep checking in, everything stays green. If I stop, things start progressing:

  1. Active — All good. Checked in recently.
  2. Warning — It's been a minute. I get a nudge.
  3. Notified — Silence continues. A trusted contact gets a heads up.
  4. Triggered — Significant silence. Automated actions fire.

Each tier has a configurable threshold in days. The transitions only go one direction until I check back in, which resets everything to active. I'm keeping the specific actions vague on purpose — the interesting part is the mechanism, not what it does when it fires.

The status widget at the top of this post is live, by the way. It's pulling from the actual database. If it says "Active," then I'm still here. If it says something else, well, the system is doing its job.

If the switch ever fully triggers, a page goes live at /memento-mori. Right now that link 404s, which is the whole idea — if you can reach it, something went wrong. If you can't, we're good.

Building It

Stored State vs. Computed

The first real design decision was whether to store the status explicitly or compute it on the fly. You could derive the current tier purely from the lastCheckin timestamp — check how many days have passed, map it to a tier, done.

I went with storing it in Redis, and here's why:

Side effects are tier-gated. When the system moves from "warning" to "notified," it sends an email. If you're computing status on every request, you need a separate mechanism to track whether you already sent that email. Storing the status means the escalation logic runs once, updates the state, fires the email, and moves on. Clean.

Auditability. I can look at Redis and immediately know what state the system is in. No reconstructing anything from timestamps. The stored status is the source of truth.

Decoupling. The cron job that handles escalation and the page that displays status don't share any logic. One writes, the other reads. They don't even know about each other, which is exactly how I want it.

The Stack

This runs on the same infrastructure as the rest of my site, because I'm not spinning up something separate for this:

  • Upstash Redis for state. Three keys: deadman:last_checkin, deadman:status, and a flag for whether certain actions have executed. The entire data model is three strings. Redis is kind of perfect here — serverless, fast, and I'm not going to hit the free tier limit with three keys.
  • Vercel Cron runs the escalation check daily. It reads state, checks if a tier boundary got crossed, and updates accordingly.
  • Resend for transactional email. When the system needs to notify someone, it sends a plain, simple email. Nothing fancy.

The Check-in

Checking in is a single authenticated POST request. Bearer token with timing-safe comparison — standard stuff. It resets lastCheckin to now and sets status back to "active."

I wanted check-ins to be as automatic as possible — not something I have to remember to do. So it triggers when I open my laptop, or when I open a specific app on my phone. Things I already do every day without thinking about it. The whole point is that if I'm living my normal life, the switch stays green. It only notices when I stop.

The Escalation Loop

The cron job is the core of the whole thing. Every day it:

  1. Reads current state from Redis
  2. Computes days since last check-in
  3. Checks if any tier threshold has been crossed
  4. If yes: updates the stored status and fires the tier's action
  5. If no: does nothing

That's it. No queues, no retry logic, no distributed systems complexity. It's one function that runs on a schedule and makes simple decisions. The most important property of a deadman switch is that it actually works when you need it to, and reliability comes from simplicity. I would rather have something boring that I trust than something clever that might fail.

The Live Widget (ISR)

The status widget on this page uses Next.js Incremental Static Regeneration. The page gets built statically but revalidates every hour, so when you load this you're seeing cached HTML that's at most an hour stale — not a live API call. The widget is fast, doesn't expose any public API surface, and doesn't hammer Redis on every page view.

Data flows server-side only: Redis → server component → client component prop. No public endpoints, no client-side fetching. If you open your network tab, you won't see any status requests, because there aren't any.

Memento Mori

"Remember that you will die." It's a Stoic thing. I'm not going to pretend I've read Marcus Aurelius or that this project is some profound philosophical statement — I built a cron job that sends emails. Let's not get carried away.

But I do think there's value in just... not ignoring it? Most people know they're going to die in the same way they know they should floss. It's true, sure, but it's not really actionable information on a random Tuesday night when you're desperately trying to catch up on book club reading, or deciding to ignore that completely and build a deadman switch instead.

The switch is nice because it turns something abstract into something concrete. I open my laptop, the check-in fires, and I go about my day. I don't sit around thinking about mortality. It's the least dramatic relationship with death possible, which is exactly what I wanted.

The palm reading was nonsense. But it got me to actually build something instead of just thinking about it, so I'll give her that one.