So from whatI can tell, everything is working exactly how you (and I) expect ... except for where th
So from whatI can tell, everything is working exactly how you (and I) expect ... except for where the bill lands 
reconnecting-websocket package that Cloudflare Agents use for this purpose. I have forked that for my own purposes but you could just use that.
RpcTarget?ctx.id always valid even when you got to the DO via getByName(), meaning I can use it as a "return address" for in-Cloudflare communication even if my client-side application always uses the name?getByName is just a convenience utility mapping to .get(DO.idFromName() I think0.128 GB-s * 3600 seconds_per_hour * 744 hours_in_month = 342_835 GB-s/month and at the price $12.50/million GB-s that's 4.285 USD/month (342_835/1_000_000*12.50).0.128 GB-s vs 0.125GB-s