For the sake of simplicity, we will stick to Flyway for our database migrations. The only difference will be in how we wrap the migration code. We will Encapsulate the code properly within an IO to defer side effects.
While we’re at it, we may just as well write our migration code using the interpreter pattern (it is popular under the name “tagless final” in Scala).
The database layer should provide programmatic access to the database and also manage changes in the database. The latter is called migrations or evolutions. We will use Flyway as the tool to manage our database schema.
Flyway uses raw SQL scripts that have to be put into a certain location and follow certain naming conventions. This is the /db/migration (under the resources folder) in our case. The files also have to be named following the convention VXX__some_name.sql, where XX is the version number. Please note that there are two underscores between the version prefix and the rest of the name.
Because our database schema is straightforward, we get done quickly.