If it operates on state, then it basically can't - though the underlying mechanic of erlang:cancel_timer and then a message flush could.

I think you could do both parts - a cancel_timer(?SEND_TIMEOUT_MSG, #state{}) -> #state{}. function and a generic 'cancel timer and flush' function in a util module.

If this tcp drain work is ultimately successful, I'm considering rewriting the http drain code to use the tcp drain design.