Context:
We are using blue-green deployment, which means that during release, containers with old and new code coexist temporarily for a period between 1 to 10 minutes, not in seconds.
Issue:
During the release, a migration is included to add a new column to an existing table. This causes an error in the code running inside the old container.
attributes = MyTable.find(X).attributes
MyTable.create!(attributes)
=> ActiveModel::UnknownAttributeError unknown attribute 'xxx' for MyTable
Cause:
The schema cache in the old container does not contain information about the newly added column. The code retrieves information from the database instead of the schema cache when using the attributes method, which contains the new information.
Objective:
Is there a way to avoid ActiveModel::UnknownAttributeError while maintaining blue-green deployment? The solution should work even when adding non-null columns. Changes to the application or release procedures are both acceptable.
2
Answers
Rails loads the database schema and its table definitions when the server starts. That means the database needs to be migrated before the code is deployed which used newly added columns.
Depending on your deployment setup, the safest way would be to deploy the database migration first and then deploy the new model second. Or you need to ensure that the database migration runs before the app server is started with the new code.
What’s usually suggested to do in this kind of situation is to deploy a version of an app which ignores the column to be added, e.g.:
After the deployment that prepares the app to ignore such a column, a deployment with the migration can be run, after which a new deployment which un-ignores the column (and most likely makes use of that new column) can be pushed. This should allow you to avoid the issues you are having.