Spring-Boot execute data.sql in one profile only
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
If you want Spring Boot to run seed data in only one profile, the clean solution is to make SQL initialization profile-specific rather than trying to hide conditional logic inside data.sql. In current Spring Boot versions, that usually means using profile-specific configuration with spring.sql.init.* properties and pointing the desired profile at its own SQL file.
Why the Default data.sql Is Too Broad
A plain data.sql in src/main/resources is classpath-wide. If SQL initialization is enabled, Spring Boot will try to use it regardless of whether you intended it only for dev, local, or test.
That is a problem when seed data should exist in one environment but not in another. You do not want demo users or fake lookup rows appearing in production by accident.
So instead of one global data.sql, use:
- no global seed file by default
- profile-specific SQL file names such as
data-dev.sql - profile-specific
spring.sql.init.data-locations
A Simple Profile-Specific Setup
Start with a neutral base configuration.
Then enable SQL initialization only in the profile where you want it.
Now when the dev profile is active, Spring Boot loads data-dev.sql. When other profiles are active, SQL seeding stays off.
Example SQL File
The SQL file itself remains ordinary SQL.
The important part is not the file content. It is that the file is only referenced by the intended profile.
Running with the Profile
You can activate the profile in several ways. One common option is the command line.
During startup, Spring Boot uses application-dev.yml, sees that SQL initialization is enabled, and runs the configured script.
For production, omit that profile or activate a different one:
In that case, the base configuration keeps SQL seeding disabled.
When You Need Schema and Data Together
If the profile should also create schema objects, configure both schema and data locations for that profile.
That keeps the whole initialization path scoped to the intended environment.
An Alternative: Custom Initializer Bean
If the condition is more complex than profile matching, you can create a small Spring bean that runs SQL only when a certain profile is active.
This works, but it is usually more verbose than using spring.sql.init.*. Prefer configuration properties unless you truly need code-level control.
When to Use Flyway or Liquibase Instead
For small seed datasets, profile-specific SQL init is fine. For serious schema evolution and repeatable data migrations, Flyway or Liquibase is often the better tool.
Those tools give you versioning, ordering, and deployment discipline. Spring Boot's automatic SQL init is convenient, but it is not meant to replace full migration management in a complex application.
A common pattern is:
- Flyway for schema and durable migrations
- profile-scoped SQL init only for local development seed data
That division keeps things predictable.
Common Pitfalls
A common mistake is leaving a global data.sql on the classpath while also trying to add profile-specific behavior. The global file can still run if initialization is enabled.
Another issue is using old configuration keys from older Spring Boot versions. Current Boot uses spring.sql.init.*, so copying outdated spring.datasource.initialization-mode examples can lead to confusion.
Teams also sometimes seed production accidentally because the wrong profile is active in deployment. Treat profile selection as part of deployment safety, not as an afterthought.
Finally, do not use ad hoc startup SQL for long-term schema migration strategy. That is where dedicated migration tools are better.
Summary
- Use profile-specific configuration to control when seed SQL runs.
- Keep SQL init disabled by default and enable it only in the intended profile.
- Point
spring.sql.init.data-locationsat a profile-specific SQL file. - Prefer
spring.sql.init.*properties over older deprecated configuration styles. - Use Flyway or Liquibase when the problem is migration management, not simple seeding.
Related reading
- Spring-Boot How do I set JDBC pool properties like maximum number of connections?
- Spring-Data-MongoDB Failed to convert from type after upgrade to 2.0.7 with custom converter
- spring4.2.1, hibernate5 integrate abstract method error
- Spring4 Scheduled Transaction throws no transaction is in progress at flush for mutliple dataSources
- spring-boot Fatal error compiling invalid target release 17
- spring-boot gradle plugin can't be found
- Spring - No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
- Spring / RabbitMQ transaction management

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.