Optimize API performance with Gzip Compression in Golang

An application’s performance is a crucial aspect that directly impacts user’s satisfaction and search engine rankings. In one of the projects I worked in, we got users complaining about our application’s performance. On digging further, we found that the response body of an API we used was huge and the application spent long time on downloading it. While we took minor steps like removing unused fields, breaking down the response, etc., the most effective technique that solved our problem was compression. Gzip compression being widely used method, we compressed the HTTP response with Gzip to optimize the performance. In this blog post, we will explore how you can implement Gzip compression in Golang with Gin web framework to optimize your API’s performance and provide an exceptional user experience.

The Importance of Compressing HTTP Responses

Why should we consider compressing HTTP responses?

  • Improved Loading Times: Compressing responses reduces data transfer times, leading to faster page loads, optimized application performance and a better user experience.
  • Efficient Bandwidth Usage: Smaller response sizes consume less bandwidth, making your application more cost-effective, particularly for users on limited data plans or slower connections.
  • SEO Advantages: Search engines consider page load speed when ranking websites. Implementing Gzip compression can positively impact your site’s SEO ranking and overall visibility.
  • Mobile Optimization: With Gzip compression, your web application becomes more mobile-friendly, catering to users with bandwidth constraints and varying network quality.

Implement Gzip Compression

To implement Gzip compression in your Golang project with Gin Framework, we can use the gin-contrib/gzip middleware. Contributed by opensource contributors, this is one of the middleware from Gin’s arsenal.

Adding the Gzip middleware to your project

To add the Gzip middleware, simply run the below code. This will download and install the dependency to your project. For this post, I’ll be using the Golang service that I created for my earlier post which is available in this github repository.

go get github.com/gin-contrib/gzip

Below is a snippet to import the dependency to your code

package main

import (
    "github.com/gin-contrib/gzip"
)

Adding the middleware

In the main function where I create the router, I’m adding the middleware to the router.

func main() {
    router := gin.New()

    // Enable Gzip compression
    router.Use(gzip.Gzip(gzip.DefaultCompression))
      
    // routes and handlers go here

    router.Run(":8080")
}

Adding a router to test

In order to test this, I created a JSON file under ./resources/large_json_data.json with size approximately 5 mb along with a static route to serve this JSON file.

func main() {
    router := gin.New()

    // Enable Gzip compression
    router.Use(gzip.Gzip(gzip.DefaultCompression))
      
    // other routes and handlers go here

    // http://localhost:8080/large-data-static
    router.StaticFile("/large-data-static", "./resources/large_json_data.json")

    router.Run(":8080")
}

Let’s run the server with command go run .

Requesting for compressed data

Before testing the server, let’s see how to make the request. To request for a compressed response, the client should have the request header Accept-Encoding. Even if compression is enabled in the server, response body will be compressed only if the client adds the header Accept-Encoding: gzip. There are other directives apart from gzip but I’ll be focusing only on gzip. When the server responds with Gzip compressed data, the response header should include Content-Encoding: gzip. Checkout Content-Encoding for more details. Below points are the behavior with and without the header.

  1. Given that Gzip compression is enabled in server, when client requests with header Accept-Encoding: gzip, the response is compressed. The response header will include Content-Encoding: gzip.
  2. Given that Gzip compression is enabled in server, when client requests without header Accept-Encoding: gzip, the response is not compressed.
  3. If Gzip compression is not enabled in server, regardless of requesting with Accept-Encoding header, the response is not compressed.

Let’s test

Start the server with command go run .

To test without compression, let’s invoke the API request without Accept-Encoding header using curl.

curl --location 'http://localhost:8080/large-data-static' --header 'Content-Type: application/json' > dump.txt

#output
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 5564k  100 5564k    0     0   178M      0 --:--:-- --:--:-- --:--:--  181M

To test with compression, let’s invoke the API request with Accept-Encoding header using curl.

curl --location 'http://localhost:8080/large-data-static' --header 'Content-Type: application/json' --header 'Accept-Encoding: gzip' > dump.txt

#output
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  594k    0  594k    0     0  1225k      0 --:--:-- --:--:-- --:--:-- 1226k

Without compression, the response size is 5564k but with compression, we get 594k. We achieved approximately 90% of compression 🎉

Conclusion

In this blog post, we saw about,

  • What is and how to use Accept-Encoding and Content-Encoding
  • How to optimize your application’s performance using gzip compression
  • How to add Gzip compression to your Golang code with Gin framework

Don’t miss the other posts below related to Gin Framework. Stay tuned for more such content.


I hope this post was helpful 😊. If you find this post informative, support us by sharing this with fellow programmers in your circle 😀.

For any suggestions, improvements, reviews or if you like us to cover a specific topic, please leave a comment.
Follow us on twitter @thegeeksclan and in Facebook.
#TheGeeksClan #DevCommunity

error

Enjoy this blog? Please spread the word :)