diff --git a/.air.toml b/.air.toml
index 0610088303179..069a88924388b 100644
--- a/.air.toml
+++ b/.air.toml
@@ -5,6 +5,6 @@ tmp_dir = ".air"
 cmd = "make backend"
 bin = "gitea"
 include_ext = ["go", "tmpl"]
-exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata"]
-include_dir = ["cmd", "models", "modules", "options", "routers", "services", "templates"]
+exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata", "models/fixtures", "models/migrations/fixtures", "modules/migration/file_format_testdata", "modules/avatar/identicon/testdata"]
+include_dir = ["cmd", "models", "modules", "options", "routers", "services"]
 exclude_regex = ["_test.go$", "_gen.go$"]
diff --git a/Makefile b/Makefile
index f1b6790dc507e..5805476b892fd 100644
--- a/Makefile
+++ b/Makefile
@@ -358,7 +358,7 @@ watch-frontend: node-check node_modules
 
 .PHONY: watch-backend
 watch-backend: go-check
-	$(GO) run $(AIR_PACKAGE) -c .air.toml
+	GITEA_RUN_MODE=dev $(GO) run $(AIR_PACKAGE) -c .air.toml
 
 .PHONY: test
 test: test-frontend test-backend
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 5fe4682968b34..3897b9c56bd09 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -1039,7 +1039,10 @@ func loadFromConf(allowEmpty bool, extraConfig string) {
 	// The following is a purposefully undocumented option. Please do not run Gitea as root. It will only cause future headaches.
 	// Please don't use root as a bandaid to "fix" something that is broken, instead the broken thing should instead be fixed properly.
 	unsafeAllowRunAsRoot := Cfg.Section("").Key("I_AM_BEING_UNSAFE_RUNNING_AS_ROOT").MustBool(false)
-	RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod")
+	RunMode = os.Getenv("GITEA_RUN_MODE")
+	if RunMode == "" {
+		RunMode = Cfg.Section("").Key("RUN_MODE").MustString("prod")
+	}
 	IsProd = strings.EqualFold(RunMode, "prod")
 	// Does not check run user when the install lock is off.
 	if InstallLock {