···11# Generational Read Version
2233In FoundationDB, transactions are not allowed to span generations.
44-During recovery, the current database version is advanced by 100 million (100 seconds).
44+During recovery, the database fast-forwards by 100 million versions (100 seconds).
55Because the mvcc window is only 5 million (5 seconds),
66this effectively kills any transactions that were in-progress during the recovery;
77they will fail with `transaction too old`.
88+99+## Why fast-forward?
810911There are a couple of reasons for this design.
1012···4143a new transaction with a read version from the new generation's Sequencer could attempt to read uncommitted mutations from the *last* generation.
4244That is, if we did not fast-forward, the generations' version ranges could *overlap* and there would be confusion about which mutations are being read.
4345The fast-forward fixes this because it effectively skips over those versions in the "history" of the database.
4646+4747+### Why 100M?
4848+4949+As a side note, it's not clear to me why FDB fast-forwards by 100M versions,
5050+as it appears 5M versions (or whatever the MVCC window is set to) would be sufficient.
5151+It's tempting to chalk this up to superstition (100M "just to be safe"),
5252+but this would be very uncharacteristic of FDB and its heavy focus on correctness testing and validation.
5353+5454+## Problems with fast-forward
5555+5656+The fast-forward approach is simple and elegant.
5757+If you are operating under the assumption that FDB versions are not supposed to correlate with real time,
5858+skipping 100M versions here and there is not a big deal.
5959+And this is the assumption FDB was designed under:
6060+FDB versions correlate with real time *internally* to provide a real-time-ish MVCC window,
6161+but this is an implementation detail that should not be relied upon by *users*.
6262+6363+You can imagine how that went.
6464+6565+### Versionstamp
6666+6767+Over time, versions worked their way into FDB's userspace APIs,
6868+most prominently with the "versionstamp" feature that enables the client to inject the commit version into a key or value.
6969+Versionstamps are used internally and externally (in layers/apps) to write keys into the database at a particular "time".
7070+7171+A good example is the implementation of the "automatic idempotency" feature.
7272+The authors wanted to easily clean up old idempotency keys,
7373+so they wrote them with versionstamped ids such that they can simply be range-cleared below a particular timestamp.
7474+This would be trivial, except that due to recoveries versionstamps *do not correlate with real-time*,
7575+so the authors had track recoveries and perform adjustments to the watermark to compensate.
7676+7777+At some point a Timekeeper role was added to the database to write the current versionstamp into the meta keyspace every 10 seconds.
7878+Those keys are used as a reverse lookup table (real time -> versionstamp) internally within the database (IIRC for something backup-related).
7979+This is, frankly, a pretty good hint that something has gone off the rails.