VisualCron → Apache Airflow
VisualCron has been a pragmatic Windows scheduler for two decades — but as workloads move to Linux containers and cloud, BatchFoundry converts your Tasks, Triggers, Variables, and Job Chains into clean Airflow DAGs.
VisualCron is a mature Windows-centric automation platform used widely in SME and mid-market enterprises. Its GUI-driven job authoring, rich trigger library, and nested variable substitution make it flexible on-premises — but those same characteristics become friction when an organization moves toward Kubernetes, cloud-native data platforms, and open-source orchestration. BatchFoundry handles the full VisualCron-to-Airflow migration: XML export, trigger analysis, credential migration, and a 14-day parallel-execution comparison before cutover.
Concept Mapping
The Hard Parts We Handle
- File, Folder, and Database Triggers have no 1:1 Airflow equivalent — each is mapped to the most appropriate Sensor pattern
- Nested variable substitution (e.g. {Server.IP}, {Date.Now('yyyyMMdd')}) expanded into Jinja templates or XCom values
- Job Chain conditional branching ('if exit code = X') becomes BranchPythonOperator with explicit task_ids
- VisualCron Credentials migrated to Airflow Connections with Vault / Secrets Manager backends recommended
- Windows-only execution model rehosted to Linux BashOperator or SSHOperator targeting existing Windows agents
- Per-server licensing audit before cutover to validate host counts
VisualCron Job to Airflow DAG
Before
<!-- VisualCron Job: Daily Sales ETL -->
<Job Name="Daily_Sales_ETL">
<Trigger Type="Time" Schedule="Daily 02:00" />
<Tasks>
<Task Type="Execute" Path="C:\etl\extract.bat" />
<Task Type="Execute" Path="C:\etl\transform.bat" />
<Task Type="SendEmail" To="ops@example.com" />
</Tasks>
</Job>After (Airflow)
# Airflow DAG: daily_sales_etl
from airflow.decorators import dag
from airflow.operators.bash import BashOperator
from airflow.operators.email import EmailOperator
from pendulum import datetime
@dag(schedule="0 2 * * *", start_date=datetime(2025, 1, 1), catchup=False)
def daily_sales_etl():
extract = BashOperator(task_id="extract",
bash_command="/etl/extract.sh")
transform = BashOperator(task_id="transform",
bash_command="/etl/transform.sh")
notify = EmailOperator(task_id="notify",
to="ops@example.com",
subject="Daily sales ETL complete",
html_content="OK")
extract >> transform >> notify
daily_sales_etl()Ready to migrate from VisualCron?
Talk to a BatchFoundry engineer about your workload estate.
Talk to an Engineer