Contents

  1. Introduction
  2. The App
  3. Provisioning
  4. Gotchas
  5. Links and References

Introduction

In this article, we’ll be exploring Heroku’s offering for deploying Go web applications that are backed with a MySQL database. We’ll be looking at an example app, provisioning a database addon for our Heroku dyno, and some tricky gotchas that one might encounter with this endeavour. Let’s get started!

The App

I’ve been learning Go the past few weeks, and have decided to make some projects to bolster my knowledge. I decided to follow the API and Microservices section of FreeCodeCamp’s Curriculum. The third project, a URL Shortener App, is the first project from the API and Microservices section that requires a data store. I’ve contemplated for a while and have been really tempted to just write the data on disk (to a txt or csv file) to keep things simple. But I realized it would be fun to try out deploying a Go app that uses MySQL as its data store onto Heroku.

The app itself is pretty straightforward. You give it a link, it stores it, and gives you a short link that redirects you to the link you’ve originally provided. It uses nothing but the standard library, except from the 3rd party MySQL driver.

Here’s a live demo and the source.

Provisioning

In order to deploy this app from my local machine to Heroku, I need to provision a dyno and an instance of MySQL (called ClearDB). To do this, issue the following commands

$ heroku login # Make sure you already have an account
$ heroku create <your-app-name-here>
$ heroku addons:create cleardb:ignite

We’re live! You can now access the app through https://<your-app-name-here>.herokuapp.com/. Now is also the time to get your database credentials with the following command:

$ heroku config | grep CLEARDB_DATABASE_URL
CLEAR_DATABASE_URL => mysql://alphanum-username:alphanum-password@us-cdbr-iron-east-01.cleardb.net/heroku_alphanum_name?reconnect=true

This is the ClearDB connection string that you’ll need to connect to the database instance that we have just provisioned. We’ll use this later.

Gotchas

  • Make sure your Procfile is properly formatted

Heroku’s configuration file named Procfile is actually quite strict with its syntax. A common pitfall I see (and have encountered myself) is the following mistake:

web:bin/my-app # Wrong

This will throw an H14 error (see heroku logs --tail) because of the missing space between web: and bin/my-app

web: bin/my-app # Correct
  • Use and set the proper environment variables

Heroku uses an environment variable, aptly named PORT, to determine which port a web app will run on. This means you can’t (and shouldn’t, anyway) hardcode the port within your app. You should use the os module and load the port from the environment variables:

The database credentials shouldn’t be hardcoded within the app as well, obviously. You should use an environment variable for this, which we will call DATABASE_URL:

import (
    "os"
    "log"
)

func main() {
    port := os.Getenv("PORT")

    if port == "" {
        log.Fatal("$PORT is not set")
    }

    dns := os.Getenv("DATABASE_URL")

    if dns == "" {
        log.Fatal("$DATABASE_URL is not set")
    }
}
  • Properly format the DNS string

We’ve already covered how to get the ClearDB url earlier, but we can’t just plug it in as our DATABASE_URL and be done with it. So let’s say the CLEARDB_DATABASE_URL that we’ve been assigned is:

mysql://alphanum-username:alphanum-password@us-cdbr-iron-east-01.cleardb.net/heroku_alphanum_name?reconnect=true

We have to format it as follows:

alphanum-username:alphanum-password@tcp(us-cdbr-iron-east-01.cleardb.net)/heroku_alphanum_name

Note that the host part is wrapped inside tcp()

You should now have a fully working Go web application backed by a MySQL database!


Got any feedback or suggestions? Feel free to send me an email or a tweet.
Ciao!