Ask
96
@visa_run_val ·

one durable object per room or one DO plus a KV index for 500 live rooms Durable Objects

Collaborative editor. Expect up to 500 rooms active at once, 2 to 20 people each, WebSockets, and the document state per room is small — tens of kilobytes.

I keep going back and forth. One DO per room feels like the intended design but 500 objects sounds expensive and I cannot find a clean way to list them. One central DO with a KV index is easier to reason about but obviously has a single-thread problem somewhere. This is a side project so the bill matters.

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @first_repo_finn · 4mo ago · 3 replies

    One per room, without hesitation. That is precisely the shape the primitive exists for: each room gets its own single-threaded actor, its own WebSocket set, its own storage, and consistency for free because there is exactly one of it.

    One central DO means every keystroke in every room serialises through one thread. You will hit that wall somewhere around twenty active rooms and the fix at that point is the rewrite you are trying to avoid.

    On cost, the thing that decides whether this is affordable is hibernation. Use state.acceptWebSocket() rather than holding sockets in memory, so an idle room with people connected is not billing wall-clock duration the entire time they are idle. In a collaborative editor most rooms are idle most of the time — people leave tabs open. Without hibernation you are paying for 500 rooms continuously; with it you are paying for the handful actually being typed in.

    Listing rooms is a separate problem and should not influence this. Keep room metadata in D1 and let the DOs handle only live state.

    71
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @visa_run_val · 4mo ago

      "Listing is a separate problem" is the part I had tangled up. I was picking a live-state architecture based on wanting a room list on a dashboard.

      24
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @deploy_friday_ok · 4mo ago

      Hibernation is the entire ballgame for anything socket-shaped. Three idle users in a room look identical to three active ones from a billing perspective if you hold the sockets yourself, and that difference is the whole reason people post "why is my DO bill like this".

      18
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @ridgeline_rowan · 4mo ago

    Second the per-room design, and be careful where you put the index. A single DO holding "which rooms exist" recreates the bottleneck you were trying to avoid, just at a lower request rate — until you add presence and it gets written on every join and leave.

    D1 for room metadata, KV for things read constantly and written rarely, DO storage for live document state. Three stores sounds like a lot until you notice each one is doing the thing it is good at.

    43
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @resole_ruth · 4mo ago · 2 replies

    Numbers from something similar, since "is it expensive" deserves a real answer: about 300 rooms, hibernating sockets, storage in the low hundreds of megabytes total. Bill sat under ten dollars a month and roughly 80% of it was request count, not duration. The cost model punishes chattiness far more than it punishes having many objects.

    19
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @visa_run_val · 4mo ago

      That is reassuring and also tells me to batch the cursor position broadcasts, which right now fire per mousemove because of course they do.

      11
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @deploy_friday_ok · 4mo ago

    Think about placement before you have users in two hemispheres. idFromName puts the object near whoever touched it first, so a room created by someone in Sydney and joined by five people in Berlin means every one of those five is paying a Pacific round trip on every edit. If rooms are regional in nature, look at location hints at creation time.

    31
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @hemline_hank · 4mo ago · 2 replies

    Make sure you can clean up. Objects are cheap, storage you never delete is a slow leak, and there is no button anywhere that says "drop everything". Decide the deletion story on day one while you still only have test rooms.

    14
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @first_repo_finn · 4mo ago

      Alarm-based TTL is the tidy version: on last disconnect set an alarm for a day out, and when it fires check whether the room is still empty and call deleteAll() if so. Twenty lines and it runs forever.

      10
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report