Cut over: migrate from Upstash to KiviDB

With the RDB file, the downtime is from the export until clients have switched: stop writes before you export. To keep it to seconds, use a live copy:

With the RDB file, the downtime is from the export until clients have switched: stop writes before you export. To keep it to seconds, use a live copy:

  1. Rehearse. Copy into a test KiviDB, point a test deployment of your application at it, and run the verify script.

  2. Turn on keyspace notifications on Upstash. Upstash supports them through CONFIG SET:

    redis-cli -u "$UPSTASH_URI" CONFIG SET notify-keyspace-events KEA
    
  3. Start the long copy. RedisShake with ksn = true (keep rdb_restore_command_behavior = "rewrite": a key that changes is copied again over the old copy), or RIOT with --mode LIVE. Leave it running. If the notifications are not on, neither tool says so: the copy simply misses the changes.

  4. Check it has caught up with the verify script. A few keys changing in flight is expected.

  5. Stop writes to Upstash. Put the application in maintenance mode, or stop the writers.

  6. Let the last changes arrive (a few seconds), stop the copy, and compare DBSIZE on both sides.

  7. Switch the application to KiviDB (see below) and deploy it.

  8. Watch errors and latency. Turn the notifications off on Upstash (CONFIG SET notify-keyspace-events ""), and keep the database, untouched, until you are sure.

Rolling back. Until step 7 nothing points at KiviDB and nothing is lost. After it, writes go only to KiviDB, and copying them back is narrower than copying them in. KiviDB's DUMP payloads are in its own format, which Valkey refuses (ERR DUMP payload version or checksum are wrong) and Upstash can be expected to refuse too, so RedisShake and RIOT's default mode can't write them. RIOT reads through Lua scripts, so it also needs Lua on the KiviDB it reads from. What works is RIOT with --struct, reading from a KiviDB that has Lua (the lua or full build, or the Lua add-on on Cloud):

riot-standalone-4.3.0-linux-x86_64/bin/riot replicate --struct \
  --source-tls --source-cacert kividb-ca.pem --source-user kividbapp --source-pass "$KIVIDB_PASSWORD" \
  --target-tls --target-user default --target-pass "$UPSTASH_PASSWORD" \
  --ttl-tolerance 10s \
  rediss://your-name.cloud.kividb.io:6380 \
  rediss://my-db-12345.upstash.io:6379

Rehearse it if you may need it. The simplest safety net needs no copy at all: for the first days after the switch, have the application write to both KiviDB and the Upstash database (reads from KiviDB only), so the Upstash database stays current and switching back is a change of address. Without that, and without Lua on KiviDB, the way back is to keep the Upstash database untouched and accept losing the writes made since the switch.

For a cache your application can rebuild, there is a simpler way: point the application at an empty KiviDB and let it fill.