I have a question for deployers. Let’s say there’s a new security patch that comes out, and it introduces a new setting that doesn’t have a good universal default. (Each deployer will need to make their own decision.)
And… let’s say you don’t notice it in the release notes, or perhaps you apply the patch without adding the new setting. Which of these scenarios would you prefer, and why?
The setting is required for server startup, so after upgrading or patching your server exits during startup (or possibly, all pages fail to load) with an informative log message. You’ll notice quickly, but if you don’t test in a staging environment first, this could result in a lot of user-facing errors.
The setting is given a default that is acceptable for most deployments, but not all, so there’s a chance you’ll just have buggy-seeming behavior (potentially user-facing misbehavior) after upgrading or patching.
My preference would be that if there is no value explicitly set, a default value is used and a warning is sent to the administrators (e.g. using django.core.mail.mail_admins). However I’m not sure that the platform has a mechanism for sending notices to administrators that’s going to work across most deployment strategies? So another option that I would suggest is to include a django migration that raises an error if the setting is not set, but otherwise the system will work and a default is used. That way, there are no direct user visible errors but the sysadmins who are deploying the security update will definitely notice a failed database migration.
Barring such options, I would go for making the setting required. I think that large/critical deployments always have staging instances and rollout procedures exactly for this reason.
I was about to say that my preferred option is to have the web app crash when the setting is missing, but then I really like @braden’s suggestion to crash a migration instead. This makes it crystal clear to system administrators that a new setting is required, and yet the platform remains available for users.
On the other hand, this behaviour is not quite consistent with the way other settings are handled in Django. The Django SECRET_KEY is one example of a setting for which “bad” values will crash the platform: Settings | Django documentation | Django
So I suggest we take a similar route: define an empty value as default, then crash at runtime if the value is empty.