A developer who needs to work on a new feature should never make direct changes to the schema (models/fields/etc.) in the primary environment.
There are multiple reasons for this:
the changes might severely interfere with the work of the editors working on the live website;
the changes might modify the format of some API call responses that are required by the live website, and break the experience for end users;
the changes could be accidentally wrong, and produce significant loss of data.
Using environments, you can instead follow this safe workflow:
Create a new sandbox environment, forking the primary one. From now on, exclusively work inside the sandbox — this will safeguard you from all the problems just mentioned above!
Create a branch in the Git repository of your website/app, and inside it, start reading content from the sandbox environment instead of the primary environment;
Manually write a migration script (or auto-generate it). As we'll cover thoroughly in the next sections, a migration script is just a sequence of API calls to the Content Management API that produces changes to the schema of an environment;
Run the migration script on the sandbox environment to apply the changes;
Adapt the code of your website/app to the changes.
If you make any changes to the migration script after running it, you can re-test it by simply repeating steps 1, 3, and 4.
Just like Git branches, environments let multiple development teams work simultaneously on different changes to the content schema, without interfering with each other. Everyone has their own copy of the schema, and can test/iterate freely.
As long as you are working in a sandbox environment, you may not even need a migration script, you can just make your changes to models/fields using the interface... but eventually the time will come to merge your work and changes into production.
The primary environment at this point, however, may have changed significantly; we can't just promote our sandbox environment to primary, because it is stuck at a past snapshot of the primary environment made at the time of the fork, and we would lose all the work done in the primary environment from that point forward.
Having an explicit migration script makes your changes reproducible. It allows the exact same steps tested in the sandbox environment to be performed on the primary environment itself!
Let's see exactly how in the next section.
By writing migration scripts by hand, you lose one of the core strengths of DatoCMS: the convenience of a graphical interface for editing your content schema.
Fortunately, you can also auto-generate migration scripts! In this case, you can make the necessary changes to the schema via the UI, and get back a migration script with a sequence of API calls that produce the same results.
Once everything is ready to be shipped in production, follow this process — of course, it can be adapted to your specific deployment workflow:
Turn on Maintenance Mode, so that during the deployment process no one can write new data on the primary environment. Before enabling maintenance mode, DatoCMS will warn you if other collaborators are currently working on some content, so you can decide to postpone the deployment and contact the editors.
Merge the Git feature branch containing the adaptation of your website/app code to the new changes;
Fork the primary environment into a new sandbox environment, and re-run the migration script on it;
Promote the sandbox environment to be the new primary. The old primary environment will in turn become a sandbox, ready to be promoted again as an instant rollback in case of errors you might find later on in production. We put no expiration dates on sandbox environments, which means that development teams can potentially create multiple restore points;
Deploy your website/app with the merged changes;
Test that everything works on your live website/app;
Turn off maintenance mode to allow content editors to get back to their regular work on the new primary.
To learn more, visit the Apply migrations to primary environment guide.
If the team relies heavily on automated testing, environments can be created programmatically and just for the duration of a test. Once it has successfully passed, the environment can be programmatically deleted.
Environments enable continuous integration by allowing you to create a “template environment” to use during tests. This template maintains the exact state you need to run your tests. Because environments are meant to be used as temporary entities for isolation, you don’t need to run any clean-up tasks.
Instead, just delete and recreate a new environment for every test.