Heroku: Go with MySQL Notes
Tags: go, heroku, mysql
Published: 2020-03-28 03:12:51

---
layout: post
title: "Heroku: Go with MySQL Notes"
comments: false
slug: heroku-go-mysql-notes
description: "Deploying a Go web application backed with a MySQL data store"
categories: [heroku, go, mysql]
keywords: "heroku, go, mysql, cleardb"
author: John Alcher
tags: Go, Heroku, MySQL
cover: https://www1.assets.heroku.com/assets/wallpapers/go/screen-070f110649f62beff690a73f5c60bbcffc90bc10564445a62d93295eeafc4d57.png
canonical_url: https://johnalcher.me/2020/heroku-go-mysql-notes/
published: true
---

<center><small>Originally hosted on my [blog](https://johnalcher.me/2020/heroku-go-mysql-notes/)</small></center>

---

![](https://www1.assets.heroku.com/assets/wallpapers/go/screen-070f110649f62beff690a73f5c60bbcffc90bc10564445a62d93295eeafc4d57.png)

## Contents

1. [Introduction](#introduction)
2. [The App](#the-app)
3. [Provisioning](#provisioning)
4. [Gotchas](#gotchas)
5. [Links and References](#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](https://golang.org/) the past few weeks, and have decided to make some projects to bolster my knowledge. I decided to follow the [API and Microservices](https://www.freecodecamp.org/learn/apis-and-microservices/apis-and-microservices-projects/) section of [FreeCodeCamp's Curriculum](https://freecodecamp.org/learn). The third project, a [URL Shortener App](https://thread-paper.glitch.me/), 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](https://url-shortener-microservice-go.herokuapp.com) and the [source](https://github.com/alchermd/url-shortener-microservice).

## Provisioning

In order to deploy this app from my local machine to Heroku, I need to provision a [dyno](https://www.heroku.com/dynos) and an instance of MySQL (called [ClearDB](https://devcenter.heroku.com/articles/cleardb)). To do this, issue the following commands

```bash
$ 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:

```bash
$ 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:

```Procfile
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`

```Procfile
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`:

```go
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!

## Links and References

- [Go Official Website](https://golang.org/)
- [Go Web Examples](https://gowebexamples.com/)
- [Go MySQL Driver](https://github.com/go-sql-driver/mysql)
- [ClearDB on Heroku](https://devcenter.heroku.com/articles/cleardb)
- [Heroku Error Codes](https://devcenter.heroku.com/articles/error-codes)