May 28, 2024
Vercel is most commonly known for deploying Javascript frameworks, so why host a Go application on it? Vercel has an incredibly generious free tier that allows for 100,000 free serverless invocations. If you’re just building a hobby project, it’s unlikely you’d ever exceed this. DNS is also included in this, so you’re able to use a custom domain at no extra cost.
First, lets create a new project. I’ll call this go-chi-vercel-example.
mkdir go-chi-vercel-example
Lets now initialise our Go project and install Chi
cd go-chi-vercel-example
go mod init github.com/<YOUR_USERNAME>/go-chi-vercel-example
go get -u github.com/go-chi/chi/v5
Now, we’ll make our handler
mkdir handlers && cd handlers
touch hello_world.go
We should now have a file structure that looks like this
.
├── go.mod
├── go.sum
└── handlers
└── hello_world.go
We’ll now create our handler that will be called for our requests.
// handlers/hello_world.go
package handlers
import (
"net/http"
"github.com/go-chi/render"
)
type HelloWorldHandler struct{}
func NewHelloWorldHandler() *HelloWorldHandler {
return &HelloWorldHandler{}
}
func (h *HelloWorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
render.JSON(w, r, map[string]string{"hello": "world"})
}
Now that our handler has breen creatd, we’ll need to create our router to handle the requests.
To do this, we’ll be following the docs from Vercel.
Lets create our api.
mkdir api && cd api
touch index.go
Let’s now build out our Chi router.
// api/index.go
package api
import (
"net/http"
"github.com/go-chi/chi/v5"
"github.com/<YOUR_USERNAME>/go-chi-vercel-example/handlers"
)
func Handler(w http.ResponseWriter, req *http.Request) {
r := chi.NewRouter()
r.Get("/", handlers.NewHelloWorldHandler().ServeHTTP)
r.ServeHTTP(w, req)
}
Now, we need to tell vercel how to interact with this, so we’ll create a vercel.json file.
touch vercel.json
Now, add the following into it to tell vercel to redirect all requests to our handler.
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"rewrites": [
{
"source": "/(.*)",
"destination": "/api"
}
]
}
Your API is now ready to deploy to Vercel and the final project should look something like this.
.
├── api
│ └── index.go
├── go.mod
├── go.sum
├── handlers
│ └── hello_world.go
└── vercel.json
View the live version here and the repo here
As vercel only deploys serverlessly, this may lead to cold starts affecting response time if your API is not used frequently. Additionally, Go support at Vercel is still in Beta so this may not be safe for any production applications.