Skip to content

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.

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 new setting to the JSONB column like rate_limits in the ApplicationSetting model.
    • Update the JSON schema validator for the column like rate_limits validator.
  • If there isn't an existing JSON column which you can use then:
    • Add a new JSON column to the application_settings table 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 the new setting to the list of visible attributes.
  • Add the new setting to it to 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 ApplicationSetting model.
  • 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.rb script to generate a definition YAML file at config/application_setting_columns/*.yml and update the documentation file at cells/application_settings_analysis, based on db/structure.sql and the API documentation. After the definition file is created, ensure you set the clusterwide key to true or false in it. Setting clusterwide: true means that the attribute value are copied from the leader cell to other cells in the context of Cells architecture. In most cases, clusterwide: false is 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
end

Model validation example

validates :new_setting,
          length: { maximum: 255, message: N_('is too long (maximum is %{count} characters)') },
          allow_blank: true

Migrate a database column to a JSONB column

To migrate a column to JSONB, add the new setting under the JSONB accessor. Follow the process to add a new application setting.

You can use the same name as the existing column to maintain consistency. During the transition period, 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.

You must follow the process for dropping columns to remove the original column. This a required multi-milestone process that involves:

  1. Ignoring the column.
  2. Dropping the column.
  3. Removing the ignore rule.

Dropping the original column before ignoring it in the model can cause problems with zero-downtime migrations.