Preventing billing fraud by bad actors when working with websocket-driven Durable Objects

I’ve been trying to make heads or tails of the pricing documentation for Cloudflare Workers.

From my understanding, a client may establish a websocket connection with a Worker which then may forward a request to a Durable Object. At that point, as long as that Object is “active” (which includes when any websocket is connected to it), that time is billed as the wall time.

We’ll assume that this is a chat application where any anonymous user can create a room. There are a lot of questions here, but all of these build up together and are related to one another:

Question 1

If one person creates an empty chat room and does not use it but sits in there for the entire month, will the usage count as one active Durable Object for that entire month?

Question 2

Is there a way to time out the user for inactivity?

Question 3

Related to question 2:

I hear that a limit of Durable Objects is that there is a 30 second limit per request. Does that mean the client would need to keep retrying a connection every 30 seconds/on close?

If so, a total idle time value could be added and an Object deleted if a websocket request happened, say, after 5 minutes of total inactivity.

Question 4

What if the programmer made a mistake and the above timeout code did not work? Is there a way to prevent or at least detect a Durable Object being idle for too long?


With message-limited rate limiting per IP and limiting initial Upgrade requests per IP, some semblance of billing fraud prevention can be reached. But it all depends on the pricing model. I’d personally prefer to allow users to idle forever in a chat room if it didn’t cost me anything.

The ability to connect to a Durable Object from a web client and just listen to any changes to it is probably incredibly common for refugees from Firestore or DynamoDB like me. This is especially the case if certain information can be changed or redacted before it reaches subscribers.

Any help is much appreciated!