# Building a Personal Background Job System

11/15/2021

This weekend I built something that many have tried and most have succeeded to do - Build a background job system. This time, however, it has a bit of a twist in that this is for personal, for fun jobs. This means I don't need globally-distributed, fault-tolerant services. Nor do I need fancy things like exponential backoff for retries or health probes. I simply needed something to run some code and tell me the results (gasp, how original). So with that goal in mind, I started off with a list of ideals to see if I could make something work.

# Core Goals

  • Easy to add new jobs - If I have a new script I want to deploy, I don't want to have to spend a few hours configuring it
  • Easy to update existing jobs - If a script is broken or needs some tweaking, again, I don't want to have to spend a few hours fixing it.
  • Low overhead - Since this is for personal use I don't have the deep wallets of a company to build the ideally engineered system, rather I have a budget of just a few dollars / month.
  • Minimized infrastructure - I want to manage as little infrastructure as possible, ideally none.
  • Notification system - I need to be able to see the results in an easily consumable method.

# Considered Approaches

# Luigi

Spotify's Luigi (opens new window) was the first option that came to mind. I had seen it released a few years back and the name stuck in my mind. After perusing the README.md it became obvious pretty quickly that it was far more complex than I needed, so I moved on.

  • Easy to add new jobs - ⛔️
  • Easy to update existing jobs - ⛔️
  • Low overhead - ⛔️
  • Minimized infrastructure - ⛔️
  • Notification system - ⛔️

# Airflow

I know what you're probably thinking - If Luigi was too complex, well Airflow sure as heck will be too. And to that I say, you're right. I actually gave this a bit deeper look because I had used it before so was hopeful that the previous experience would enable me to iterate quickly. I was able to set up the docker-compose.yml file pretty quickly and had a running copy of Airflow! When it came time to start writing jobs however, I remembered there was a significant amount of overhead in the job definition files. Given than alongside the sheer amount of resources required by the docker-compose file, I arrived at the conclusion that this too would likely be a bit too powerful for my needs

  • Easy to add new jobs - ⛔️
  • Easy to update existing jobs - ✅
  • Low overhead - ⛔️
  • Minimized infrastructure - ⛔️
  • Notification system - ⛔️

# Azure Functions

I finally arrived at a hosted function solution. As I had investigated the other options, I just couldn't get past the ease of using hosted functions and finally realized that this was likely the right path. Azure has a great integration with GitHub actions that enables you to trivially set up CI/CD with the function, meaning any code changes automatically make it to production on merge with main. Not only was it easy to update, but since consumption plan functions bill only on time used and have a generous free tier I was able to run this for $0/month!

So lets review my check list:

  • Easy to add new jobs - ✅
  • Easy to update existing jobs - ✅
  • Low overhead - ✅
  • Minimized infrastructure - ✅
  • Notification system - ⛔️

# Solving Notifications

Azure Functions fit the bill with virtually everything except for having a simple mobile notification system. While I didn't have a full solution for this yet, I set to work building the background job system on Azure Functions. While I was working on the system, I received a slack update for my App's sales and a 💡 went off - Slack is a ready-made mobile notification service! Since the API to send a slack message is so straightforward, I was able to quickly add logging to slack to record the results of my jobs. Once that was set up, all I had to do was sign into my workspace on my phone and enable notifications for the given channel.

# Conclusion

So far, GitHub CI/CD + Azure Functions + Slack has been working flawlessly (all 2 days). Setup was trivial and I'm hopeful that maintenance will continue to be low so I can spend time writing jobs rather than worrying about them running.