ContentsThe library

How a Password Is Stored

Upgrading Something You Cannot Read

Last timeEverywhere Else It Appears

You decided on better settings and a better function. The rows you already have were written with the old one, you cannot read any of them, and nobody is going to reset forty thousand passwords.

Why a batch job cannot do it

You have read the course and decided on a memory-hard function with

settings measured on your own hardware. Now look at the forty thousand

rows you already have, written years ago with a fast function and a

default repetition count.

The instinct is a batch job: read each row, compute the new value, write

it back. It does not work, and the reason is the entire point of the

first lesson. The new stored value is a function of the password. You do

not have the password. You have a one-way value derived from it, and that

is all you will ever have.

So the upgrade has to happen at the one moment the plain password passes

through your system, which is a successful login. Everything in this

lesson follows from that single constraint.

FIG 1How many rows convert in a period
rows converted to the new scheme
accounts in the table
share of accounts that log in during the period, which is well under one
Rows upgraded u is the number of accounts a times the share of them that log in during the period l. Nothing you do to the database moves this number, which is why the migration is paced by your users rather than by your deployment, and why the plan has to include the accounts for which l is zero.

The one moment you have it

The path is short. A login arrives. Read the scheme, the cost setting and

the random value from the row, as the fourth lesson insisted, and verify

with those. If verification fails, nothing happens.

If it succeeds, you are holding the plain password and you have just

proved it is correct. Compute a new stored value with the current scheme,

a fresh random value and the current settings, write the row, and carry on

serving the login.

FIG 2Verify with the old, store with the new
Eleven steps and only three of them are new. The decisive detail is the first: because every row carries its own scheme and settings, two schemes can coexist indefinitely, and that is what turns an impossible bulk conversion into a background process paid for by ordinary logins.
FIG 3The same table during a migration
plaintext
account      | scheme     | cost            | state
-------------|------------|-----------------|---------------------
a.okafor     | argon2id   | m=64MB t=3 p=1  | current, converted
t.bergstrom  | pbkdf2     | 10000 rounds    | old, awaiting a login
m.whitfield  | argon2id   | m=64MB t=3 p=1  | current, new account

the rule for each login:
  read the scheme from the row, never from configuration
  verify with what the row says
  on success, if the scheme is not current, rewrite the row
  write scheme, cost, random value and stored value as one unit

the rule for each new account:
  always the current scheme, never the old one
Three rows, two schemes, one table, and every row verifiable with what it carries. The field order is fixed so a row can be parsed back, and the scheme name is first because it decides how the rest is read. Nothing here requires a flag day or a reset.

Three mistakes are worth naming because each is common. Upgrading on a

failed login, which writes a row from an unverified password. Writing the

new stored value while leaving the old random value or cost in place,

which produces a row that cannot verify. And creating new accounts under

the old scheme because the account creation path was never changed, which

means the migration never finishes.

The lesson stops here

5 more paragraphs to go

You have read the opening. The rest of the argument, the problems that check whether it landed, and the lines worth keeping at the end all come with a plan.

The first lesson of every course in the library reads the whole way through, free, so you can see exactly what the rest of them are.

See the planThe contents

This is the reading half

Starting the course gives you your own copy of it. Every idea on every page has problems standing under it, marked with a reason rather than a tick, and any sentence you do not believe can be opened and argued with. None of that can happen on a page nobody owns.

The contents

The rest of this course

  1. 01The Only Thing the Table May Hold
  2. 02The Number That Makes the Rest Necessaryopening only
  3. 03Two Rows That Look the Sameopening only
  4. 04The One Place Slowness Is the Featureopening only
  5. 05A Quarter of a Second, Ten Thousand Times at Onceopening only
  6. 06The Comparison That Tells You How Close You Wereopening only
  7. 07The Stored Row Was Never the Only Copyopening only
  8. 08Upgrading Something You Cannot Readyou are here

Read alongside