Kickbet is a web app where you can guess the results of football matches and compare your guesses with those made by your friends. I built Kickbet specifically for the 2022 FIFA World Cup.

Player scores table

The rules are simple. You score:

When the tournament is finished, the person with the most points wins.

The architecture

SendgridKickbet appRedisPostgreSQLSMTP

The deployment

DigitalOcean dropletDocker engineNGINXKickbet appRedisPostgreSQLS3The worldHTTPHTTPSdaily backup

I use an ansible playbook to set up the VM with:

NGINX is configured to handle HTTPS and to rewrite the domain in the cookies to/from localhost to the production domain.

Whenever I need to deploy another version of the application, I use another playbook which deploys the docker-compose.yml with the application (a specific docker image tag) and its dependencies.

I also set up two cron jobs:

Everything runs on a single $6 / month DigitalOcean droplet.

The tech stack for the app

Kotlin, Spring Boot, React. The React app is bundled and served as static content by the Kotlin app.

The fun stuff

Lessons learned

Redis not really needed, but doesnt’t hurt at all to use it

For such a simple app with such a small number of users, I believe I could simply use the database to store the user sessions. Anyway, I think I spent less time configuring redis than I would’ve spent setting up the DB schema for storing the sessions.

Remember to set up the firewall

I initially forgot to set up the firewall on the VM. It didn’t even take 24 hours to kill my redis instance. I believe this stackoverflow post describes what happened to my server.