How to enable Scheduled jobs by profile in spring?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
To enable @Scheduled jobs only for specific Spring profiles, annotate the scheduling configuration class or the bean containing scheduled methods with @Profile("production"). This ensures the @Scheduled methods only run when the specified profile is active. Alternatively, use a @ConditionalOnProperty to toggle scheduling based on a property, or externalize the cron expression and set it to "-" (disabled) in non-production profiles.
Method 1: @Profile on the Configuration Class
With this setup, @EnableScheduling is only activated when the production profile is active. Without it, the @Scheduled annotation is ignored entirely.
Method 2: @Profile on the Scheduled Bean
This lets you define different jobs for different profiles.
Method 3: @ConditionalOnProperty
This is more flexible than @Profile because it does not tie scheduling to a specific profile name.
Method 4: Externalized Cron Expressions
Set the cron expression to "-" (disabled cron) per profile:
The special cron value "-" was introduced in Spring 5.1 and disables the scheduled task entirely.
Method 5: Programmatic Scheduling
For full control, configure tasks programmatically:
Setting the Active Profile
Approach Comparison
| Approach | Granularity | Flexibility | Spring Version |
@Profile on config class | All jobs on/off | Low | Any |
@Profile on bean | Per-bean | Medium | Any |
@ConditionalOnProperty | All jobs on/off | High | Spring Boot |
Cron "-" | Per-job | High | Spring 5.1+ |
SchedulingConfigurer | Per-job | Highest | Any |
Common Pitfalls
- Putting
@Profileon individual@Scheduledmethods instead of the bean or config class:@Profileis a bean-level annotation — it controls whether the bean is created, not individual methods. Annotating a method with@Profilehas no effect. Put it on the@Componentclass or the@Configurationclass. - Enabling
@EnableSchedulingglobally without profile awareness: If@EnableSchedulingis on your main application class (not a profiled config), scheduling infrastructure is always active. Move it to a separate@Configurationclass with@Profileor@ConditionalOnProperty. - Using
"-"as a cron expression on Spring versions before 5.1: The"-"disable feature was added in Spring 5.1 (Spring Boot 2.1). On older versions,"-"is treated as an invalid cron expression and throwsIllegalArgumentExceptionat startup. - Forgetting that
@Scheduledrequires a no-arg void method: The method annotated with@Scheduledmust returnvoidand take no arguments. If the method has parameters, Spring silently ignores the scheduling annotation. - Not setting a thread pool for scheduled tasks: By default, Spring uses a single-thread executor for all
@Scheduledtasks. If one task blocks, all others are delayed. Configure a pool withspring.task.scheduling.pool.size=5or define a customTaskSchedulerbean.
Summary
- Use
@Profile("production")on the@EnableSchedulingconfig class to disable all jobs in non-production environments - Use
@Profileon individual@Componentbeans to enable different jobs per profile - Use
@ConditionalOnPropertyfor property-based toggling independent of profile names - Use cron expression
"-"(Spring 5.1+) to disable individual jobs per profile - Always configure a thread pool size for scheduled tasks to avoid single-thread bottlenecks

