Migrations
Migrating the schema of a database as features are built is an imporant part of Evolutionary Database Design. Platter's branching model was built with this incremental design process in mind, and makes database migrations a less error-prone process.
While the Postgres Client
does not have any built-in schema migration methods, the schema can be altered directly with query
. In many cases, this will be sufficient. For those that would like a more systematic migration experience, we recommend migrate
, an abstract migration framework for Node.
This guide will show you how to use migrate
and @platter/migrate-store
to incrementally change the schema of your Postgres databases. For this example, you will learn how to build a schema for a basic blog API that returns collections of posts
and authors
.
#
PrerequisitesA Postgres database. See the "Setting Up Postgres" section of the Quick Start for more information. Like the Quick Start, this guide will use a database named my-new-database
.
#
Creating MigrationsInstall
migrate
as adevDependency
with:migrate
uses timestamped.js
files in amigrations
directory to schedule migrations. To generate your first migration, run:...which will create a
./migrations/1613143187252-add-posts.js
file on your behalf (example timestamp). Your project structure will look like this afterwards:Migration files export
up
anddown
methods that correspond to applying and reverting migrations, respectively. Replace the contents of your*-add-posts.js
file with the following:migrations/$TIMESTAMP-add-posts.jsFrom here, migrate your schema with:
...and reverted those changes with:
#
Tracking MigrationsBy default, migrate
only stores migrations locally. This approach does not work well with branching databases, as the state of a database will often be different from the state of those migration-tracking files. Instead, migrations can be tracked in the database by implementing a custom store.
Platter has created a custom store implementation that uses Postgres Client
s to track migrations separately in each branch of a database.
Install
@platter/migrate-store
as adevDependency
with:@platter/migrate-store
expectsPLATTER_API_KEY
andPLATTER_POSTGRES_CLIENT
environment variables on invocation, andmigrate
expects the store implementation to be provided through a--store
option. Putting that together, migrations can now be performed like so:
#
Transactional MigrationsNow that each branch of a database tracks its own set of migrations, it's time to add another migration that includes more complex logic that needs to be performed in multiple steps. This is a perfect use-case for a Transaction
.
posts
should haveauthors
, of course. Create a migration forauthors
with:Replace the contents of your new
*-add-authors.js
migration file with the following:migrations/$TIMESTAMP-add-authors.jsRun the
up
migration command once more, and you'll notice that only the second migration was run. This will be true for anyone that clones your project or branches this database in the future!
#
DeploymentTo see how migrations interact with popular build systems and branch deploys, take a look at the guide for Netlify Functions.