We ended up creating a custom Pulumi resource, that wraps the creation and execution of the Fargate task. And then hold off on updating our ECS services until the database migration task is “complete”.
I’m happy to share the code with you, although there are a lot of baked-in assumptions that are specific to our environment. (Such as the use of ECS, so we run the task within the existing cluster. Or the specific directory we have our database migrations, and package up the container, etc.)
But in short, if you would like to, “running a fargate task to run database migrations” is a thing you can do with Pulumi. But you’ll need to run it on ~every update to ensure that the deployed code matches the expected database schema. If you’d like to learn more about that approach, happy to help out. (But some other technique might be a better fit for your setup.)