I just wasted two month time of development regarding my loyalty bot, for real?

The “viewer” list on site could be cached for minutes while the JOIN/PARTs are cached into batches every 10-30 seconds (don’t remember the exact interval). People losing or reconnecting at an inopportune moment could easily cause a discrepancy. It’s also good to note that you don’t technically need to be in a channel to send messages to it, so if you’re adding people who chat to your list, you could also end up with a higher count.