Hey! I’m one of the OpenChat devs (there are 3 of us).
Each time a new user registers an account, an update command is sent to our ‘user_index’ canister.
That canister creates the user a new canister, installs the latest version of the user canister wasm, and initialises it, passing in the new user’s principal in the init args.
To upgrade the user canisters, we push the new canister wasm to the user_index canister, which then upgrades each of the user canisters using ‘heartbeat’.
We also have a group_index canister which works in the same way but for groups.