Duplicate existing content when a field is duplicated

We are making a mobile app relying on Dato for its content.
Because it takes time for users to upgrade their mobile app, we need to make sure every change we make to our Dato model are backward compatible and we often duplicate fields (and mark the old one as deprecated) when introducing breaking changes to our models.

One frequent pain point when doing this is that duplicating a field does not duplicate its existing content, so we need to write a migration script to retrieve the content of the old field and add it to the new one, which is pretty tedious, and can be pretty complex for things like Structured text or blocks.

It’d be super useful to us if there was an option (via a checkbox) to duplicate the existing content when duplicating a field, so we wouldn’t have to write this script manually every time.

Hi @simon.treny,

Normally, our customers use environments for this instead of field-specific changes. When you fork an environment, everything gets carried over – content and schema – and it only takes a few seconds. Would that work for you?

Hi @roger,

Thanks for the follow up!
I’m not sure environments would work for us as:

  • We still want members from old app versions to see the latest content (even if they won’t benefit from the changes made afterwards on duplicated fields)
  • We do this very often (like once a week), and I’m worried we would end up with way too many environments (but maybe that’s not an issue?)

Do you still think environments would be the proper way to handle this?

Hi @simon.treny,

This sounds like an intricate situation that you should probably discuss and test out with your team, but in general, I think yes, environments could still work for this situation if you use some sort of rotation and promotion system on them.

Some examples…

Promote sandbox to primary directly

This is for team workflows where you have a feature & content freeze on your primary env while you work on a new feature, i.e., no changes are being made to the primary env while you’re working in the sandbox.

The benefit of this approach is that you can keep all new schema and content in the sandbox environment. When you promote it, we just flag it as the new primary and API calls will start using it and you don’t lose anything.

  • Fork your primary into a new sandbox (like new-feature-x) so you can safely work on it without disrupting real users or editors
  • Once the new feature sandbox is ready and tested against your app, you can “promote” it to become the new primary. API calls to primary should immediately hit that new primary now.
  • Optionally, you can rename the old primary to something else for clarity (e.g. prod-backup-2024-10-02)
  • Delete the oldest backup every week (either manually or on a cron job)

Work in a sandbox, then apply a migration to the primary

In many teams, though, the previous method won’t work because the primary environment needs to stay mutable while development on a new feature continues. Editors might have to add new content, webhooks might change, etc.

In that case, you can still fork the primary and work on a sandbox, but then retroactively apply the changes to your primary environment via a migration script: https://www.datocms.com/docs/scripting-migrations/apply-migrations-to-primary-environment

The downside is that this will still only migrate schema from the sandbox back to the primary, not any new content you’ve added there :frowning: You’d have to use API calls to copy over any content afterward.


Alternatively, I wonder if you could make some frontend app changes and have each app version fetch from a specific environment? e.g.

  • Current app version is fetching from your main (primary) env
  • That gets forked. New app version fetches from main-2024-10-02 instead. Current version users are unaffected.
  • Do this several times, and eventually (when there are no more users left on the oldest app version/env), start the rotation again.

I don’t know your workflow or content needs well enough to say if this is the best solution, though. It may be the case that an API call is still easier :frowning:

(Edit: And of course, let’s leave this feature request open too. Hopefully we can just make that process easier for you in the future).