diff --git a/airflow/cli/commands/webserver_command.py b/airflow/cli/commands/webserver_command.py index 5399f8ba64045..17d48ad8dae4f 100644 --- a/airflow/cli/commands/webserver_command.py +++ b/airflow/cli/commands/webserver_command.py @@ -422,11 +422,17 @@ def webserver(args): run_args += ["airflow.www.app:cached_app()"] - # To prevent different workers creating the web app and - # all writing to the database at the same time, we use the --preload option. - # With the preload option, the app is loaded before the workers are forked, and each worker will - # then have a copy of the app - run_args += ["--preload"] + if conf.getboolean("webserver", "reload_on_plugin_change", fallback=False): + log.warning( + "Setting reload_on_plugin_change = true prevents running Gunicorn with preloading. " + "This means the app cannot be loaded before workers are forked, and each worker has a " + "separate copy of the app. This may cause IntegrityError during webserver startup, and " + "should be avoided in production." + ) + else: + # To prevent different workers creating the web app and + # all writing to the database at the same time, we use the --preload option. + run_args += ["--preload"] gunicorn_master_proc: psutil.Process | subprocess.Popen diff --git a/airflow/config_templates/config.yml b/airflow/config_templates/config.yml index f868a6c6ead58..f61f6baca05dc 100644 --- a/airflow/config_templates/config.yml +++ b/airflow/config_templates/config.yml @@ -1400,7 +1400,8 @@ webserver: reload_on_plugin_change: description: | If set to True, Airflow will track files in plugins_folder directory. When it detects changes, - then reload the gunicorn. + then reload the gunicorn. If set to True, gunicorn starts without preloading, which is slower, uses + more memory, and may cause race conditions. Avoid setting this to True in production. version_added: 1.10.11 type: boolean example: ~