Skip to main content
  1. Posts/

Rethinking migrations in Golang Applications

··621 words·3 mins
Author
Hairizuan Noorazman
Software engineering experiments, implementation notes, and lessons learned.

This is more of a reminder post for me that every aspect of application development is critical and sufficient thought should be put behind it. This time around, it’s on database migration within applications.

As a matter of convenience, I use a Golang ORM library called Gorm that would handle database interactions. It is definitely a convenient way to manage and handle database records. Even if people mention how bad ORMs is, at the end of the day, you would still want to manage the data coming from application in some form of struct where the types are obviously set. If this was the goal, even if you use the raw mysql golang libraries - you would still write up code that would map the raw database responses to Golang structs before it’s being passed around the application.

However, this time around, this post isn’t exactly aiming to focus on the ORM portion of the library but more of the database migration bit. The GORM library comes with some functionality that helps users with database migration simply based on Golang structs. All we need to do is denote the structs that would be managing the data we wish to store in database with some gorm struct tags, and then, the said information will be used by Gorm library to create the necessary tables/columns that would be used to store the data on the database. The convenient function that is being used to handle it is the AutoMigrate function. https://gorm.io/docs/migration.html

In general, the AutoMigrate function works fine in most cases. At the end of the day, you would want to work with latest schema that works with your application. One of the biggest benefits of this function is that it allows you to do database migrations without needing to think of writing sql migration scripts etc - which is usally a major pain. Database migrations are usually one of the main reasons for why applications cannot be updated simply:

  • There is too much data in database and a naive database migration would result in an outage
  • A table that the application is using needs be broken up, maybe another round of database migration needs to be done?
  • A bad database migration due to programming error and it’s required for the database schema to be reverted
  • Deploed application and its database schema are extremely outdated. It’s impossible to update it unless one uses old binaries and keep swapping/upgrading binaries till the right database schema is reached for updating the application to the latest version.

The AutoMigrate function kind of nudges the developer in the direction to not think of such scenarios. However, reality always strikes back at the worst possible timings and it’s always better to have such capabilities in place rather than not having it at all.

An alternative (albeit better in my opinion) for handling database migration is to utilize something like golang-migrate? https://github.com/golang-migrate/migrate. The library provides a CLI but we can embed said functionality into our application. One of the primary capabilities it provides is a “migration” database schema table that allows us to track the version of the database schema we are on. At the same time, it also allows us to update database schema one at a time. We can jump multiple database migrations at one go or we can go one database migration at a time to ensure database will not suffer any outage.

Here is a sample application from my many sample golang application that utilizes the go-migrate library. https://github.com/hairizuanbinnoorazman/Go_Programming/tree/master/Web/basicMigrate

For reference on all other posts with regards to the building of the slides to video application:

Related

CORS with Golang Microservices and Elm Frontend is difficult

··1597 words·8 mins
I am still building up my personal pet project: https://github.com/hairizuanbinnoorazman/slides-to-video; the aim of this project is a personal one - to build up a set of microservices that is able to be deployed in various ways such as locally via Docker Compose or even to Kubernetes or the serverless Cloud Run platform on Google Cloud Platform. There was a previous blog post describing an initial part of this journey: Lessons on building the project - Part 1

Lessons from building Slides to Video App - Part 1

··1766 words·9 mins
A long time back, sometime in 2019 (which is almost an eternity ago ), I kind of did up an application that can take some slides saved in a pdf file and generate a video out of it. I kind of talked about it in a lightning session during the following event at Google Devspace https://events.withgoogle.com/la-kopi-serverless/. The input to the application would be the slides in a pdf format as well as some sort of “script”. The words in the script would be used to generate the voiceover and then it would be used as part of the video. Essentially, the aim of the app would be create a “presented” version of the slides in a video form without requiring a person to present it. Everything about it is just generated via tools/products available on GCP.

Nginx as API Gateway - focusing on auth_request directive

··1245 words·6 mins
On virtual machine How to “protect” api requests https://www.nginx.com/blog/deploying-nginx-plus-as-an-api-gateway-part-1/ Mostly is the auth_request directive Microservices are a software architectural style that structures an application as a collection of loosely coupled, independently deployable services. Each service in a microservices architecture represents a specific business capability and communicates with other services through well-defined APIs (Application Programming Interfaces). These services are designed to be small, focused, and can be developed, deployed, and scaled independently. Its a somewhat common architectural pattern that many companies go to when it comes to scaling out their development teams to build out their product.