Building a Microservices Cloud Backend using Go and PostgreSQL

marcuskohlberg

Marcus Kohlberg

Posted on December 6, 2023

Building a Microservices Cloud Backend using Go and PostgreSQL

😬 Building microservices applications can be a pain. Normally you need to deal with a lot of boilerplate, and it can be hard to ensure end-to-end type-safety.

πŸ’‘ This guide shows you how to deploy a fully type-safe microservices application in Go β€” implementing the backend for a Trello application as an example.

This is what our backend architecture will look like, consisting of two services each with their own PostgreSQL database:

backend architecture

To build our app, we'll be using Encore, a backend development platform that provides a type-safe Infrastructure SDK for declaratively defining infrastructure in Go code.

We'll then use Encore to automatically provision and deploy our application.

πŸš€ What's on deck:

  • Install Encore
  • Create your backend app from a template
  • Run locally
  • Deploy to Encore's free development cloud

πŸ’½ Install Encore

Install the Encore CLI to run your local environment:

  • macOS: brew install encoredev/tap/encore
  • Linux: curl -L https://encore.dev/install.sh | bash
  • Windows: iwr https://encore.dev/install.ps1 | iex

πŸ”¨ Create your app

We'll be starting from a template that has two services, each with a couple of API endpoints and their own databases. (See the architecture diagram above.)

When you have installed Encore, create your application from the example app using this command:



encore app create my-app-name --example=trello-clone


Enter fullscreen mode Exit fullscreen mode

🏁 Run your app locally

Before running the application, make sure you have synced the project dependencies by running go mod tidy from the project root folder.

Also make sure that Docker is installed and running, it's required when running Encore applications locally that use SQL databases.

With that out of the way, let's start the application using this command:



encore run


Enter fullscreen mode Exit fullscreen mode

You should see this:

Image description

πŸ•Ή Open the local development dashboard

While encore run is running, open http://localhost:9400/ to view Encore's local developer dashboard.

Here you can see automatic API documentation, try your APIs with the API explorer, and study your application behavior using Encore's built-in distributed tracing.

Local development dashboard

πŸ“ž Call the API

Now that your app is running, you can ping the board.Create endpoint to create a Trello board. Either from the API explorer in the local dev dashboard, or using cURL:



curl 'http://localhost:4000/board.Create' -d '{"Name":"my board"}'


Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Once you've called the API, you can view a trace of the request from the local dev dashboard.

trace in local dev dashboard

πŸ€” How it works: Defining API endpoints

Let's take a look at the code implementing the endpoint we just called:



// Create creates a new board.
//encore:api public
func Create(ctx context.Context, params *CreateParams) (*Board, error) {
    b := &Board{Name: params.Name, Created: time.Now()}
    err := sqldb.QueryRow(ctx, `
        INSERT INTO board (name, created)
        VALUES ($1, $2)
        RETURNING id
    `, params.Name, b.Created).Scan(&b.ID)
    if err != nil {
        return nil, fmt.Errorf("could not create board: %v", err)
    }
    return b, nil
}


Enter fullscreen mode Exit fullscreen mode

πŸ’‘ With Encore you define API endpoints by adding the //encore:api annotation to any normal Go function. At compile time, Encore then generates the boilerplate code necessary to turn this into a real API endpoint. (Learn more in the docs)

πŸ€” How it works: Creating microservices

With Encore you create a microservice by defining one or more APIs within a regular Go package.

Encore recognizes this as a service, and uses the package name as the service name. When deploying, Encore will automatically provision the required infrastructure for each service.

On disk it might look like this:



/my-app
β”œβ”€β”€ encore.app          // ... and other top-level project files
β”‚
β”œβ”€β”€ hello               // hello service (a Go package)
β”‚Β Β  β”œβ”€β”€ hello.go        // hello service code
β”‚Β Β  └── hello_test.go   // tests for hello service
β”‚
└── world               // world service (a Go package)
    └── world.go        // world service code


Enter fullscreen mode Exit fullscreen mode

πŸ€” How it works: Making API calls

Calling an API endpoint looks like a regular function call with Encore. Import the service package as a regular Go package using import "encore.app/package-name" and then call the API endpoint like a regular function. Encore will then automatically generate the necessary boilerplate at compile-time.

πŸ’‘In the example below, we import the service package hello and call the Ping endpoint using a function call to hello.Ping.



import "encore.app/hello" // import service

//encore:api public
func MyOtherAPI(ctx context.Context) error {
    resp, err := hello.Ping(ctx, &hello.PingParams{Name: "World"})
    if err == nil {
        log.Println(resp.Message) // "Hello, World!"
    }
    return err
}


Enter fullscreen mode Exit fullscreen mode

πŸ’‘This means your development workflow is as simple as building a monolith, even if you use multiple services. You get all the benefits of function calls, like compile-time checking of all the parameters and auto-completion in your editor, while still allowing the division of code into logical components, services, and systems.

Then when compiling your application, Encore uses static analysis to parse all API calls and compiles them to proper API calls.

πŸš€ Deploy to the cloud

Commit the new files to the project's git repo and trigger a deploy to Encore's free development cloud by running:



git add -A .
git commit -m 'Commit message'
git push encore


Enter fullscreen mode Exit fullscreen mode

After triggering the deployment, you will see a URL where you can view its progress in Encore's Cloud Dashboard.πŸ‘ˆ

It will look something like: https://app.encore.dev/$APP_ID/deploys/...

From there you can also see metrics, traces, and connect your own AWS or GCP account to use for production deployment.

πŸŽ‰ Great job - you're done!

You now have the start of a scalable Go microservices backend running in the cloud, complete with PostgreSQL databases.

Keep building with these Open Source App Templates.πŸ‘ˆ

If you have questions or want to share your work, join the developers hangout in Encore's community on Discord.πŸ‘ˆ

πŸ’– πŸ’ͺ πŸ™… 🚩
marcuskohlberg
Marcus Kohlberg

Posted on December 6, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related