Migrating Cookiecutter templates to Backstage Software Templates: the short answer on effort
Most teams that already run a Cookiecutter library want to offer the same templates through a Backstage portal without rebuilding every one of them. The short answer is that the move is usually a question of which templates can run as-is through fetch:cookiecutter and which need rewriting with the native fetch:template action. That split depends on two things: the template's dependencies (Python packages, system binaries, hook scripts that call external tools) and where the scaffolder will execute them. A template that only renders files and needs nothing beyond what the scaffolder environment provides is a strong candidate to keep. A template whose hooks assume a developer laptop usually is not.
Effort is driven by three factors. The first is template count, since every template needs an inventory, a test run and a decision about whether it stays as Cookiecutter. The second is hook complexity: post-generation hooks that install packages, call APIs or write files outside the project are where most surprises appear, and they often need more time than the rendering itself. The third is how much your Git publishing and catalog registration steps change. Backstage needs a publish action for your Git platform and a catalog:register step that writes a valid descriptor, and these steps are often the largest share of the work even when the templates themselves are simple.
Before you commit to a plan, confirm with your platform team which Cookiecutter version and Python runtime the scaffolder will use, whether the Backstage image can reach your package indexes, and which Git platform your templates publish to. Ask any implementation partner for a written list of templates classed as run-as-is, adapt or rewrite, with the hook behavior of each. The Backstage Software Templates documentation is the natural next read for the action names and their current options.
Which Cookiecutter template features map to Backstage Software Templates
This table compares common Cookiecutter features with their closest Backstage Software Templates equivalents and marks each as mapping cleanly, mapping with a caveat, or needing a rewrite. Use it to scope the migration before touching any template, and confirm each action's behavior against the scaffolder documentation for your Backstage version.
| Cookiecutter feature | Backstage equivalent | Mapping | What to confirm |
|---|---|---|---|
| Template repository | Template entity in the catalog pointing to a template.yaml in a Git repository | Maps with a caveat | Confirm the template repository layout and how the entity is registered in your catalog location list. |
| cookiecutter.json prompts | Parameters block in template.yaml using JSON Schema fields | Maps with a caveat | Prompts with conditional logic or computed defaults need manual translation to parameter schema. |
| Jinja variables in file contents | Nunjucks templating in the skeleton directory via fetch:template | Needs a rewrite | Jinja syntax differs from Nunjucks, so expressions, filters and loops must be converted and retested. |
| Jinja variables in file and folder names | Templated paths in the skeleton, rendered by the fetch step | Maps with a caveat | Check how your Backstage version renders templated file names and handles special characters. |
| Pre-generation hooks | Scaffolder actions run before fetch steps in the steps list | Needs a rewrite | Hooks that run shell scripts need a custom action or a different approach, and scripts must be reviewed for safety. |
| Post-generation hooks | Later scaffolder steps such as publish and catalog:register | Needs a rewrite | Confirm which built-in actions cover each hook and where custom actions are required. |
| Template dependencies and includes | Separate templates or shared skeleton content referenced from fetch steps | Maps with a caveat | Dependency chains may need to be flattened or split into multiple templates. |
| Running the generator as-is | fetch:cookiecutter action with the cookiecutter binary available to the scaffolder | Maps with a caveat | Confirm local versus Docker execution requirements, Python availability and the action's current options for your version. |
Local or Docker execution for Cookiecutter steps
With local execution, the scaffolder runs the Cookiecutter step as a process on the machine that hosts the Backstage backend. The Cookiecutter tooling and its Python runtime must exist on that host before any template runs, so the backend build or server provisioning becomes the place where those tools are pinned and patched.
- Install and maintain: Python, the Cookiecutter package and any template dependencies must be present on every backend host and updated through your own patch process. Nobody else will do this for you.
- Dependency control: Pin versions in your build definition and record them alongside each backend release, so a template that worked last month still runs after a host rebuild.
- Security boundary: Templates run with the backend's operating system user, its network reach and its file access. A template from a source you have not reviewed can read anything that user can read, so restrict that account and the directories it can write to.
- Scale-out: Each backend replica needs an identical toolchain. A drifted replica produces scaffolding failures that appear only on some requests, which are slow to diagnose.
Confirm in the fetch:cookiecutter documentation for your Backstage version that local execution is a supported option, and which Python and Cookiecutter versions the step expects.
With container execution, the Cookiecutter step runs inside a dedicated image. The backend host then needs a container runtime and permission to pull the image, while Python and Cookiecutter live inside the image itself. The team controls the image as a versioned artifact, which makes the toolchain easier to audit and reproduce.
- Install and maintain: Build and publish an image that contains the Cookiecutter version your library needs, then rebuild it when base image patches are released.
- Dependency control: Tag each image with a version or digest and reference that exact value in the scaffolder configuration, so every template run uses the same toolchain.
- Security boundary: A container limits file system and process reach by default, but the mounts and network access you grant determine the actual exposure. Mount only the workspace the step needs and block outbound network access that templates do not require.
- Scale-out: Every backend replica must be able to pull the same image digest, and each host must permit the backend to start containers.
Confirm in the fetch:cookiecutter documentation whether the Docker option is supported in your version, how the image is referenced, and which mounts and working directories it expects.
Running the backend on Kubernetes changes where the toolchain lives and how it is scheduled. Pods are replaced during rollouts and autoscaling, so anything installed by hand on a node disappears. The execution choice must survive pod restarts, replica changes and cluster policy, and the answer differs between the two models.
- Local execution in pods: The backend image must include Python and Cookiecutter. Every rebuild of the backend image is then also a toolchain change that needs testing against your templates.
- Container execution from pods: Starting containers from inside a pod usually requires access to a container runtime or a separate execution service. That is a privilege decision your security team should review before adoption.
- Autoscaling: New replicas must start with the same toolchain, so verify toolchain version consistency on each rollout.
- Resource limits: Template runs can be heavy on memory and CPU depending on template content. Set requests and limits from measurements taken in your own test environment, not from assumptions.
Confirm in the fetch:cookiecutter documentation and your cluster's admission and runtime policies which execution options are permitted before you choose a design.
Documented paths for moving templates into Backstage
Teams with an existing Cookiecutter library have four workable paths into Backstage. Each path trades migration effort against how much of the portal's scaffolder, catalog and governance model the templates will use, so decide template by template.
Run existing templates with fetch:cookiecutter
Use the fetch:cookiecutter action to run an existing Cookiecutter template from a Backstage template without rewriting it. Supply the template's location, the variables it prompts for, and a runner where Cookiecutter is installed. Before committing, confirm how the action executes in your deployment, because local and Docker execution need different runtime setup, and confirm that the template's pre- and post-generation hooks run in that environment. Check the action's inputs against your Backstage version.
Rewrite selected templates with fetch:template
Use the fetch:template action to convert a template into Backstage's native skeleton format, where parameters are declared in the template definition and files use Backstage's templating syntax. Supply the skeleton files, a parameter schema for each prompt, and a mapping from each Cookiecutter variable to a Backstage parameter. The main limitation is that conversion is manual: any logic Cookiecutter runs during generation must be replaced with other scaffolder steps or custom actions. Test each rewritten template against a sample run before retiring the original.
Keep Cookiecutter for one-off generation
Leave the Cookiecutter command-line tool in place for projects that do not need a catalog entry, a portal form or a repository created by the scaffolder. The input is a maintained template repository and the people who run it from their own workstations. The limitation is that these runs bypass the portal, so they do not appear in its scaffolder history, do not register components in the catalog and are outside its access controls. Confirm that your change management and asset inventory requirements accept generation outside the portal before choosing this path.
Rebuild as a new Backstage template
Start from the services teams need to create, then design a new skeleton, template definition and catalog registration for each one. The input is a named owner for the template, the target repository layout, the standards the generated output must meet, and a decision on which Cookiecutter options still matter. The main limitation is effort: every generated file, parameter and test is new work. Confirm the template definition format and available actions against the Backstage version your team runs before estimating the build.
When to rewrite a Cookiecutter template with fetch:template
Rewrite a Cookiecutter template only when a specific problem blocks running it as-is. The three triggers are templates that depend on external generators or interactive prompts that do not map to Backstage parameters, templates whose hooks run shell logic your team cannot audit or put in a container, and templates you want to change anyway to add ownership metadata and catalog entities. If none of these applies, the template can keep running through fetch:cookiecutter while the team works on other parts of the portal. Before deciding, list each prompt the template asks for and check whether it can be expressed as a field in the scaffolder form, and list each hook script and note who wrote it and whether anyone still maintains it.
Running as-is first is a reasonable starting point, and it lets you learn which parts of the template matter to developers before you commit to a rewrite. The rewrite is more than a change of action. It replaces the Cookiecutter cookiecutter.json prompts with a parameters schema in the template's template.yaml, which changes what developers see in the form and what validation runs before a scaffold starts. It also changes the test surface: the logic moves from Jinja2 hooks into skeleton files and scaffolder steps that you can exercise with the Backstage template tests. Finally, it changes ownership, because the team that maintains a native template usually owns its catalog entity, its owner reference and its change history in Git.
Confirm the current Backstage template syntax and the scaffolder action names against the version you deploy, since the templating actions and their options can change between releases. The Backstage Software Templates documentation is the place to check. Make the rewrite decision per template, not per library, and record the owner who will accept the new parameter schema, because the people who maintained the Cookiecutter hooks are often not the people who will maintain the template in Backstage.
Sequence for migrating Cookiecutter templates to Backstage in parallel
This sequence moves an existing Cookiecutter library into Backstage without a hard switch day, so teams can compare generated output on both routes before the portal becomes the default. Each phase ends with a check that tells you whether the next phase is safe to start.
Inventory every template and its dependencies
The platform team lists each Cookiecutter template with its owner, the repositories it generates into, the hooks it runs, the variables it asks for, any Jinja filters or extensions it depends on, and how often teams actually use it. Template owners confirm the list, and unused or abandoned templates are marked for retirement instead of migration. The step is done when every template has a named owner and a recorded set of hooks and external dependencies, and the team agrees which templates are in the first wave.
Pilot two or three representative templates
Choose templates that cover different hook types, a Docker-dependent template if one exists, and one commonly used by teams. Register them in a non-production Backstage instance and run them through fetch:cookiecutter, confirming that the runner can reach the template source and that any hook dependencies exist in the execution environment. Record which hooks fail under local execution and which need the Docker route. The pilot is complete when each selected template generates a project from the portal without manual intervention.
Generate output from both routes and diff it
For each pilot template, generate the same project with identical inputs through the Cookiecutter CLI and through the portal. Compare the file trees, file contents, generated permissions, and hook side effects with a diff tool, and classify each difference as acceptable or as a defect. Catalog registration is tested at the same time: the generated repository's catalog descriptor should be discovered and imported without errors. The check passes when differences are limited to known, documented items such as timestamps or portal-added metadata.
Run both routes side by side
Keep the CLI route and the portal route both available for a defined period agreed by the platform team and template owners. Teams generate projects on either route, and the platform team logs every divergence, failed run, and support request by template. Weekly review of the log decides whether a template is ready for cutover or needs fixes first. Each template leaves this phase when its divergence log is empty or only contains accepted differences, and its catalog entry shows the expected owner and lifecycle.
Cut over the default entry point
Change the default way teams start a new project so it points to the portal template, and update the documentation, onboarding guides, and internal links that mention the CLI command. Announce the change to all template users with the list of cutover templates, the new entry point, and the support channel. Keep the CLI command working and documented as the fallback. The cutover is complete when a new project request from a cutover template lands on the portal route by default and the announcement has been acknowledged by the owners.
Define and test the rollback path
Before decommissioning anything, write the rollback steps for each cutover template: how to restore the previous default entry point, which versions of the template source and the Backstage configuration to revert to, and who approves the rollback. Test the rollback in the non-production instance and confirm that CLI generation still produces the expected output. The step is done when the rollback has been run once successfully and the procedure is stored with the template owner's record.
Decommission the old route and archive the library
After the agreed side-by-side period ends without open blockers, retire the CLI route for migrated templates, remove the duplicate template copies, and archive the Cookiecutter library in version control with a README pointing to the Backstage templates. Keep the archived repository readable so historical projects can still be traced to their template version. The step is complete when the old route is disabled, the archive is confirmed read-only, and the final divergence log and diff results are filed with the migration record.
What drives the cost and duration of a template migration
This table lists the factors that make a Cookiecutter-to-Backstage template migration larger or smaller, and what to put in a written scope. Use it to see which parts of your library will take the most review and build effort. DeployOpen does not publish prices; the quote follows from the written scope.
| Driver | What makes it larger | What makes it smaller | What to ask for in a quote |
|---|---|---|---|
| Template count | Many templates, each with its own variants and parameters | A short list of templates that cover most new services | A per-template inventory with a keep, retire or rewrite decision |
| Hook and shell logic | Pre- and post-generation hooks that run shell, install packages or call external APIs | Templates that only substitute variables with no hooks | Review of each hook and the plan for replacing it with scaffolder actions |
| Template dependencies | Templates that include shared partials, macros or other repositories | Self-contained templates with one source tree | A dependency map and the approach for each shared fragment |
| Execution environment | Local execution that needs Python and Cookiecutter installed on every runner, or Docker images to build and maintain | Running all templates in one controlled runner image with pinned versions | The runner image plan, who maintains it and how versions are pinned |
| Git platform publishing | Several source control platforms, or custom branch and pull request rules | A single platform with one publish action and existing permissions | The publish actions used, repository permissions and the review of the created repositories |
| Catalog registration and ownership | Missing owners, inconsistent system names or no existing catalog entries | Clean owner data and an agreed descriptor format | Which entity kinds are registered and how owners are validated |
| Parameter schema design | Free-text fields, cross-field rules or conditional steps that must be rebuilt | Simple parameters that map directly to existing Cookiecutter prompts | Parameter list with validation rules and the form layout agreed in writing |
| Testing depth | Golden-file comparisons, dry runs on many input combinations and CI checks on generated projects | Smoke tests on a few representative inputs | Test matrix, who signs off results and how regressions are handled |
| Teams that review output | Several platform, security or product teams approving generated projects | One platform owner who approves all changes | Named reviewers, review rounds included and the acceptance criteria |
What usually goes wrong when Cookiecutter templates move into Backstage
Moving Cookiecutter templates into Backstage changes where generation runs, who can see the results, and who keeps the templates working. The failures below tend to appear quietly after cutover, so each card names the symptom to watch for and the check that catches it early.
Generated output drifts from the CLI
The scaffolder renders a template through its own engine and context, so files can differ from what cookiecutter produces on a developer laptop. Filters, default values, file permissions and line endings are the usual differences. Before cutover, generate the same inputs both ways with the same template version, then diff the trees. Treat any difference as a blocker until the team agrees it is intended.
Hooks fail without stopping the run
Cookiecutter pre and post generation hooks can run shell or Python logic that the scaffolder does not surface in the same way. A hook that exits with an error may leave a half-built project that still appears successful in the UI. Check each hook's exit behavior in a test run, log its output, and move any step that must succeed into an explicit, visible action.
Backend hosts lose Cookiecutter dependencies
A fetch:cookiecutter step needs Python and the Cookiecutter package on the host or inside the container that runs the backend. A Backstage upgrade, a new base image or a changed Node.js version can remove them without any change to the template itself. Pin the runtime, add a smoke test that runs one template end to end after each upgrade, and record which execution mode each environment uses.
Templates with no owner or catalog entry
A template that is not registered as a catalog entity has no owner, no visible documentation and no clear person to fix it when it breaks. Teams then keep using the old copy outside Backstage, and the two versions drift apart. Give every migrated template a Template entity with an owner before announcing it, and retire the old source once the entity is live.
Sign-in gaps expose templates to wrong teams
Template visibility and the ability to run actions depend on how sign-in identities map to catalog users and groups. If the sign-in resolver is loose, or guest access is enabled, people outside the intended teams can scaffold projects or see templates meant for others. Confirm each template's access rules with a test account from a team that should not see it, and disable guest access before any migrated template is published.
Parallel runs with no cutover owner
Running the Cookiecutter library and the Backstage templates side by side is reasonable for a short period, but without a named owner the period never ends. Both versions receive fixes, teams split by preference, and the migration stalls. Name one person who decides when each template moves, set a review date per template, and record the retirement step in the same plan.
Questions teams ask before migrating Cookiecutter templates to Backstage
What does it cost to migrate Cookiecutter templates to Backstage?
The cost depends on the scope written into the agreement, not on a standard rate, and DeployOpen does not publish a price list. Expect the cost to follow the number of templates, how many of them run as-is with fetch:cookiecutter, how many need a rewrite with fetch:template, and how much of the Backstage environment is already running. One-time work covers inventory, template changes, catalog entries for each template, testing and handover. Recurring costs cover Backstage upgrades, plugin maintenance and the hosting you run. Ask any provider for a written scope that lists each template, the execution model for each one, the test environment, and what is excluded.
How long does a Cookiecutter to Backstage migration usually take?
The schedule is driven by the number and complexity of the templates, the state of your Backstage instance, and how quickly your owners review changes. Templates that run as-is through fetch:cookiecutter usually move faster than those that need rewriting as native Software Templates. Other schedule drivers include access to Git platforms, the availability of a test environment, and how many template owners must sign off. No duration is fixed for this work, so ask for a timeline tied to the written scope and to named milestones.
What must our team provide before a migration starts?
Before work starts, your team typically needs to provide:
- Access to the Cookiecutter template repositories, including any hook scripts and shared template libraries
- A named owner for each template who can approve behavior changes and decide on retirement
- Git platform access with rights to create branches and publish templates where the portal can read them
- A non-production Backstage instance and a test environment with the credentials templates need
- A list of the Cookiecutter versions and tools people use today, so behavior can be compared
Confirm the exact access model with your security team before sharing credentials.
Can our internal team migrate Cookiecutter templates without outside help?
An internal team with Backstage and template experience can migrate a small set of templates alone, and the Backstage documentation covers the scaffolder and fetch:cookiecutter action in detail. Outside help usually matters in three places: deciding which templates to run as-is and which to rewrite, designing the test approach so output is compared against the Cookiecutter original, and setting up the upgrade and ownership process that keeps templates working after handover. Check whether your team has capacity for upgrades, since the Backstage versioning policy ships a new main release each month.
Do all Cookiecutter templates need to be rewritten for Backstage?
No. Backstage can run existing Cookiecutter templates through the fetch:cookiecutter action, so a template does not have to be rewritten to appear in the catalog and produce a project. Rewriting with the native fetch:template action is a decision made per template, usually when the template needs features that are easier to maintain in Backstage's own syntax, or when the execution model must change. Decide template by template, record the reason, and keep the Cookiecutter version running until its replacement is tested and owned.
What happens to the Cookiecutter CLI workflow during the transition?
Teams can keep using the Cookiecutter CLI while templates move into Backstage, and nothing forces an immediate cutover. During the transition, the same template repository can serve both workflows if the template and its variables stay compatible. Plan the cutover per template: announce the date, publish the Backstage version, and keep the CLI path documented until owners confirm the new flow works. Remove the CLI path only after the templates that depend on it have been retired or rewritten and tested.
Which fetch:cookiecutter setting choice affects security and operations?
The main choice is where Cookiecutter runs: on the Backstage backend host with a local install, or inside a Docker container. Local execution depends on the Python and Cookiecutter versions installed on the host, so each upgrade must be checked. Docker execution isolates the tool and pins its version, but it needs a container runtime available to the backend and a reviewed image. Confirm which option your security team accepts, and check the template hook scripts, since they run code on the machine that executes the scaffolder.
How DeployOpen scopes and delivers a Cookiecutter template migration
DeployOpen plans Cookiecutter template migrations as fixed-scope work agreed in writing before any build starts. We inventory the existing template library, decide which templates run as-is through fetch:cookiecutter and which need native fetch:template rewrites, then build, test and document the result inside your Backstage instance.
How we scope
- We inventory every Cookiecutter template, its variables, hooks and Git source, and who uses it
- We classify each template as run-as-is, run-with-changes or rewrite, and record the reason
- We confirm where templates will execute (local runner or Docker) and what the runner image must contain
- The written scope lists templates, deliverables, acceptance tests and the timeline before work begins
How we build
- We wrap each in-scope template in a Backstage Software Template with parameters and a catalog-ready output
- We test generation end to end, checking rendered files, Git publishing and catalog registration for each template
- We document execution mode, runner requirements and any template changes so maintainers can follow them
- We keep changes limited to the agreed templates so that unrelated library code stays untouched
How we hand over
- You receive the template definitions, runner configuration and test cases in your own source control
- We walk your platform and template maintainers through running, updating and extending the templates
- The handover pack records which templates still depend on Cookiecutter and what each one needs to stay working
- Documentation covers the steps to add a new template and to retire a Cookiecutter dependency later
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after handover
- Retainers can cover Backstage version upgrades that affect scaffolder actions and template behavior
- We can re-run template tests when Cookiecutter, Docker images or Backstage releases change
- Ask any quote to state what recurs under a retainer and what is a one-time build cost

