Improving The Keep Alive Behavior of Gotify

Image: Gotify keep-alive traffic

Recently, I had a look at a number of frameworks to push notification messages to my mobile device based on trigger events of my cloud at home. Think of getting a notification when a service starts misbehaving or crashing, disk drives about to become full, backups finished, etc. So far I’ve used emails and XMPP messages for the purpose. While that works great it doesn’t really fit the purpose. So I was looking for something else and discovered Gotify, ‘a simple server for sending and receiving messages’.

Installation is super easy and I was up and running in just a few minutes. Also, pushing messages from the shell or in programs written in Python and other languages just requires a single line of code. On the wire, HTTP push and Websockets are used and TLS encryption with Letsencrypt certificates are thrown in for good measure. Nice! When I had a look at the traffic to and from my mobile device to the Gotify app, however, I was a bit surprised, to say the least.

As you can see in the screenshot above, the app sent or received IP packets around every 10 seconds even if no push message is sent or received. For the experiment I used non-encrypted messaging, so Wireshark nicely shows that the traffic was caused by two mechanisms:

  • TCP keep-alive messages (which would be discoverable even if encryption was not turned on)
  • Websocket Ping/Pong keep-alives.

Traffic every 10 seconds is an absolute no go for me as in effect the cellular network link could never go to idle state and the battery is drained rapidly. Quite a disappointment.

So I opened an issue at their Github page describing the behavior and its downsides. Within a day I got a developer responding that he will take a look. A few days later I got a test version with adjustable TCP keep-alive and Websocket Ping/Pong intervals. Wow! I played around with the values and finally decided to set them both to 550 seconds. This way, the chatter on the line is reduced from one packet every 10 seconds to silence periods of 6-7 minutes (*). Perfect!

All that stands in the way of me using Gotify now is for the developer to also make this work for encrypted TLS sessions. Unfortunately, adding keep-alive parameters to a Go API call breaks the application and the developer hasn’t had the time yet to have a closer look. I could have a look myself, of course, but frankly, I’ve never touched Go before and there seems to be a significant overhead involved. So let’s see.

(*) Setting the values higher is not a good idea as NAT gateways at some point run into timeouts and cut the connection. I’ll have a look at this in a follow up post)