Application settings development
This document provides a development guide for contributors to add application settings to GitLab.
Application settings are stored in the application_settings table. Each setting has its own column and there should only be one row.
Duo-related applications settings are stored in a different table.
Add a new application setting
First of all, you have to decide if it is necessary to add an application setting. Consider our configuration principles when adding a new setting.
We prefer saving the related application settings in a single JSONB column to avoid making the application_settings
table wider. Also, adding a new setting to an existing column doesn’t require a database review so it saves time.
To add a new setting, you have to:
- Check if there is an existing JSONB column that you can use to store the new setting.
 - If there is an existing JSON column then:
- Add a new setting to the JSONB column like 
rate_limitsin theApplicationSettingmodel. - Update the JSON schema validator for the column like 
rate_limitsvalidator. 
 - Add a new setting to the JSONB column like 
 - If there isn’t an existing JSON column which you can use then:
- Add a new JSON column to the 
application_settingstable to store, see this merge request for reference. - Add a constraint to ensure the column always stores a hash, see this merge request for reference.
 - Create follow-up issues to move existing related columns to this newly created JSONB column. Follow the process to migrate a database columns to a JSONB column.
 
 - Add a new JSON column to the 
 - Add the new setting to the list of visible attributes.
 - Add the new setting to the 
ApplicationSettingImplementation#defaults, if the setting has a default value. - Add a test for the default value, if the setting has a default value.
 - Add a validation for the new field to the 
ApplicationSettingmodel. - Add a model test for the validation and default value
 - Find the right view file or create a new one and add a form field to the new setting.
 - Update the API documentation. Application settings are automatically made available on the REST API.
 - Run the 
scripts/cells/application-settings-analysis.rbscript to generate a definition YAML file atconfig/application_setting_columns/*.ymland update the documentation file atcells/application_settings_analysis, based ondb/structure.sqland the API documentation. After the definition file is created, ensure you set theclusterwidekey totrueorfalsein it. Settingclusterwide: truemeans that the attribute values are copied from the leader cell to other cells in the context of Cells architecture. In most cases,clusterwide: falseis preferable. 
Database migration example
class AddNewSetting < Gitlab::Database::Migration[2.1]
  disable_ddl_transaction!
  def up
    with_lock_retries do
      add_column :application_settings, :new_setting, :text, if_not_exists: true
    end
    add_text_limit :application_settings, :new_setting, 255
  end
  def down
    with_lock_retries do
      remove_column :application_settings, :new_setting, if_exists: true
    end
  end
endModel validation example
validates :new_setting,
          length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
          allow_blank: trueMigrate a database column to a JSONB column
To migrate a column to JSONB, add the new setting under the JSONB accessor.
Adding the JSONB setting
- Follow the process to add a new application setting.
 - Use the same name as the existing column to maintain consistency.
 - During transition, Rails writes the same information to both the existing database column and the field under the new JSONB column. This ensures data consistency and prevents downtime.
 
Required cleanup steps
You must follow the process for dropping columns to remove the original column. This a required multi-milestone process that involves:
- Ignoring the column.
 - Dropping the column.
 - Removing the ignore rule.
 
Dropping the original column before ignoring it in the model can cause problems with zero-downtime migrations.
Default values
When migrating settings to JSONB columns with jsonb_accessor defaults,
remove them from ApplicationSettingImplementation.defaults because
JSONB accessors take precedence over the defaults method.
Adding a Duo-related setting
We have several instance-wide GitLab Duo settings in the application_settings table. These include duo_features_enabled (boolean), duo_workflow (jsonb), and duo_chat (jsonb).
At some point, we realized it was simpler to add new instance-wide settings to a different table. Going forward, any new Duo-related instance-wide settings should be added to the ai_settings table.
For Duo settings at the group or project level, there is also a namespace_ai_settings table.
The cascading settings framework assumes that the instance-wide setting is on the application_settings table and that group and project settings are on namespace_settings and project_settings, respectively. If you are considering adding a cascading setting for Duo, that may be a good reason to use application_settings instead of ai_settings.