Limits and gotchas: migrate from Aerospike to KiviDB

unless the write policy sends the key (sendKey, POLICYKEYSEND), and that is the default. Such records are copied as <namespace>:<set>:#<digest in hex>…

  • Records stored without their key. Aerospike stores only the digest unless the write policy sends the key (sendKey, POLICY_KEY_SEND), and that is the default. Such records are copied as <namespace>:<set>:#<digest in hex>, which the application can't look up by its own key. Either compute the same name in the application (the Aerospike client computes digests without a server: Python's aerospike.calc_digest(ns, set, key).hex(), Java's Key.computeDigest(set, Value.get(key))) or, better, write the records again from their source with the key stored. Check how many there are before you start; the loader prints the count.
  • HyperLogLog bins. Aerospike's HLL registers can't be read by PFCOUNT. The loader skips them and prints how many. Rebuild them with PFADD from the events that fed them, or, if an estimate is enough, read each count with Aerospike's hll_get_count and store it as a number.
  • Generations. They are not part of a KiviDB key. Use --gen-field if your code checks them, and keep the field current.
  • TTL on update. Aerospike resets a record's TTL on every write unless told not to; KiviDB keeps it. See TTL.
  • Record size. Aerospike records are at most 8 MiB (max-record-size), and every record is read and written whole. In KiviDB, update large documents by path (JSON.SET k $.a.b v) rather than rewriting them.
  • Float precision in JSON. In KiviDB 1.2.0, about one double in five that needs all 17 significant digits comes back from a JSON document with its last digit changed (for example, 13.326500000000001 reads back as 13.3265). Values with fewer digits (18.957, 0.1) are exact. The verify script counts these separately. If exact doubles matter, use hash mode, where each value is stored as the text the loader wrote.
  • Bytes inside lists and maps become {"$b64": "..."} objects in JSON; decode them in the application.
  • Integer and bytes map keys become strings in JSON.
  • Integer and string keys with the same text land on the same KiviDB key (see Key names).
  • Geo search fields. FT.CREATE refuses GEO and GEOSHAPE fields; use the geo: sorted sets and GEOSEARCH. Polygons and "region contains point" queries have no equivalent.
  • Secondary-index edge cases. Aerospike leaves string and blob values of 2 KiB or more out of its indexes; KiviDB's search indexes them. A query can return records that Aerospike's left out.
  • Namespace-level settings (default-ttl, eviction thresholds, stop-writes-*) have no per-prefix equivalent. KiviDB has one maxmemory per server and a maxmemory-policy; volatile-ttl (evict the keys closest to expiry) is the nearest to Aerospike's eviction.
  • Consistency. KiviDB replicas follow the primary asynchronously, like Aerospike's AP mode. There is no strong-consistency mode.
  • Multi-key commands on a sharded database. JSON.MGET and MULTI across keys on different shards answer CROSSSLOT. Use a pipeline per key, or put related keys in one shard with a hash tag ({u42}:profile, {u42}:orders).
  • Set and bin names. The prune pass splits key names at the first : after the namespace, so it assumes set names contain no :. Bin names (up to 15 bytes) become field names unchanged.