Share SQL databases between services

By default, each service in an Encore app has its own database. This approach has many benefits:

  • Which database is used and how it works is abstracted away from other services
  • The database is more isolated, making changes to it smaller and safer
  • By making the services more independent your application becomes more reliable by being able to more gracefully handle partial outages, such as if your database is temporarily overloaded or offline.

But like everything else in software engineering, there are trade-offs involved, and sometimes it's simpler and more reliable to use a single database that's accessed by multiple services. Encore makes this easy to do.

Each database in Encore is defined within a service. That service's name becomes the name of the database. Other services can then access that database by creating a database reference with sqldb.Named("dbname").

Example

Let's say you have a simple todo service, with only one table:

todo/migrations/1_create_table.up.sql

CREATE TABLE todo_item (
    id BIGSERIAL PRIMARY KEY,
    title TEXT NOT NULL,
    done BOOLEAN NOT NULL DEFAULT FALSE
);

You want to create a report service that produces various reports for internal business processes, but for simplicity you decide it makes sense to directly access the todo database. All that's needed is to define the todoDB variable like so:

report/report.go

package report

import (
    "context"

    "encore.dev/storage/sqldb"
)

// todoDB connects to the "todo" service's database.
var todoDB = sqldb.Named("todo")

type ReportResponse struct {
    Total int
}

// CountCompletedTodos generates a report with the number of completed todo items.
//encore:api method=GET path=/report/todo
func CountCompletedTodos(ctx context.Context) (*ReportResponse, error) {
    var report ReportResponse
    err := todoDB.QueryRow(ctx,`
        SELECT COUNT(*)
        FROM todo_item
        WHERE completed = TRUE
    `).Scan(&report.Total)
    return &report, err
}

With that, Encore understands that the report service depends on the todo service's database, and orchestrates the necessary connections to make that happen. And like everything else with Encore, it works exactly the same regardless of where it's running: for local development as well as in the cloud.