Making Generated Migrations More Portable with Placeholder Replacement
Published 06 August 2025
Flyway's generate
command has always been powerful for creating migration scripts that capture schema differences between environments. Now we've made those generated migrations even more useful by introducing placeholder replacement support.
Previously, when you used the generate
command to create migration scripts from schema differences, the generated SQL would contain hard-coded schema names, database names, or other environment-specific values. This meant that generated migrations were often tied to a specific environment and couldn't easily be reused across different stages of your deployment pipeline.
You would see generated migrations like this:
CREATE TABLE [dbo].[customers] (
id INT NOT NULL,
name VARCHAR(255) NOT NULL
);
What we've done is introduce the -generate.usePlaceholders=true
parameter that tells the generate command to preserve placeholder syntax in the generated migration scripts (available from Flyway v11.10.0).
Enabling the feature
When using the generate
command, simply add the -generate.usePlaceholders=true
parameter:
Command Line
flyway diff \
-diff.source=environment1 \
-diff.target=environment2 \
generate \
-generate.usePlaceholders=true \
-generate.types="versioned" \
-generate.force=true
Docker
docker run --rm \
-v "$(pwd)/conf:/flyway/conf" \
-v "$(pwd)/migrations:/flyway/migrations" \
redgate/flyway \
diff \
-diff.source=default \
-diff.target=target \
generate \
-generate.usePlaceholders=true \
-generate.types="versioned" \
-generate.force=true
Configuration
Define your placeholders in your flyway.toml
configuration file:
[flyway.placeholders]
schema="dbo"
database="myapp"
environment="prod"
What you'll see
Instead of generating environment-specific migrations, Flyway will now generate portable migrations using your placeholder syntax:
Before (without placeholder replacement):
CREATE TABLE [dbo].[customers] (
id INT NOT NULL,
name VARCHAR(255) NOT NULL
);
After (with -generate.usePlaceholders=true
):
CREATE TABLE [${schema}].[customers] (
[id] [int] NOT NULL,
[name] [varchar] (255) NOT NULL
);
Benefits
Environment Portability: Generated migrations can be deployed across development, staging, and production environments without modification.
Schema Flexibility: Perfect for multi-tenant applications where each tenant uses a different schema name.
CI/CD Integration: Generated migrations work seamlessly in automated deployment pipelines where environment-specific values are injected at runtime.
Consistency: Maintains the same placeholder patterns you're already using in your hand-written migrations.
Use Cases
This feature is particularly valuable when:
- Capturing customizations: Generate migrations from production customizations that need to be applied to other environments
- Schema synchronization: Keep multiple environments in sync while maintaining environment-specific naming conventions
- Automated drift detection: Generate corrections for schema drift that can be applied across all environments
- Multi-tenant deployments: Create tenant-specific migrations that work regardless of the tenant's schema naming