Andrew Maidah

Store Dates or Booleans?

A big pet peeve.

[object Object]
by Andrew Maidah
tl;dr prefer archivedAt over isArchived

Need To Delete But Keep An Audit Trail

Eventually, your vibecoded b2b SaaS making 50k/mo needs to delete something but you want to keep the data around.

Maybe you even promise to delete user data but you actually just soft delete and leak user data!

Even if that’s you, you can do better than isArchived.

Totally Deleting This Data

model UserDataIPromisedToDelete {
    name          String
    privateImage  String
    createdAt     DateTime
    updatedAt     DateTime
}

Let’s say you have a simple model and you want to mark this data as deleted. The obvious approach is to add a boolean flag like so:

model UserDataIPromisedToDelete {
    ...
    isArchived    Boolean  // super obvious
}

That works and now you’re excluding data in your app when isArchived === true.

When Did That Get Deleted?

A few months later, you want to know when a certain user deleted their account. After spending hours looking through your logs, you decide you need a timestamp so you add one:

model UserDataIPromisedToDelete {
    ...
    isArchived    Boolean  // super obvious
    archivedAt    DateTime? // also obvious
}

But whoops, you don’t update all parts of your code correctly and now some records have a timestamp BUT also an isArchived value of false.

Which field is accurate?

Use The Date

Get rid of the boolean and derive it from a single source: archivedAt.

type UserDataIPromisedToDelete = {
  ...
  archivedAt: Date | null
}

// use like a boolean
if (user.archivedAt) {
  // ready to leak the data
} else {
  // show user the data
}

// use the date in rendering
const archivedDate = user.archivedAt
  ? new Date(user.archivedAt).toLocaleDateString()
  : null

If the Date exists, the data was soft deleted.

Surely There’s Nothing Worse?

Oh but there is!

model User {
    name             String
    image            String
    createdAt        DateTime
    updatedAt        DateTime
    isArchived       Boolean
    isDoctor         Boolean
    isLawyer         Boolean
    isVip            Boolean
    isStabbingEyes   Boolean
}