Rails 7.1 limits the maximum length of auto-generated index names

railsNovember 14, 2023Dotby Alkesh Ghorpade

An index is a specialized database structure that facilitates efficient data retrieval operations. It acts as a pointer to the data stored in a table, enabling faster access to specific records without scanning the entire table each time a query is executed. Indexes are particularly beneficial for large tables, where the performance improvement can be significant.

Using database migrations, Rails helps developers create, update tables and add or remove indexes to the tables. But Rails auto-generated index names can run into the name is a too long error. Let's explore the issue in detail.

Before Rails 7.1

Let's say you have a Rails application with a PostgreSQL database, where you added an Employee model using migration as shown below:

class CreateEmployees < ActiveRecord::Migration[7.0]
  def change
    create_table :employees do |t|
      t.string :first_name
      t.string :middle_name
      t.string :last_name
      t.integer :department_id
      t.string :designation
      t.date :joining_date
      t.integer :salary
    end

    add_index :employees, [:department_id, :designation, :joining_date]
  end
end

As no index name is passed to the add_index command, Rails generates the index name as index_employees_on_department_id_and_designation_and_joining_date. The index name length is 65, bigger than the PostgreSQL limit of 63. When you run the migration, it fails with below error:

ArgumentError: Index name 'index_employees_on_department_id_and_designation_and_joining_date' on table 'employees' is too long; the limit is 63 characters.

To fix the issue in the Rails version before 7.1, you must pass a custom index name to the migration.

class CreateEmployees < ActiveRecord::Migration[7.0]
  def change
    create_table :employees do |t|
      t.string :first_name
      t.string :middle_name
      t.string :last_name
      t.integer :department_id
      t.string :designation
      t.date :joining_date
      t.integer :salary
    end

    add_index :employees, [:department_id, :designation, :joining_date], name: "index_employees_on_department_id_designation_and_joining_date"
  end
end

The database migration passes without raising any errors.

In Rails 7.1

Rails 7.1 limits the maximum length of auto-generated index names. The length is set to 62 to ensure it works for the default configurations of SQLite, MySQL and PostgreSQL.

  • MySQL: 64
  • Postgres: 63
  • Sqlite: 62

If the index name length is shorter than or equal to 62, Rails does not alter it. If the length exceeds 62, the index name is modified. You need to add the migration and not worry about the index name anymore. Rails will handle the index name length.

class CreateEmployees < ActiveRecord::Migration[7.0]
  def change
    create_table :employees do |t|
      t.string :first_name
      t.string :middle_name
      t.string :last_name
      t.integer :department_id
      t.string :designation
      t.date :joining_date
      t.integer :salary
    end

    add_index :employees, [:department_id, :designation, :joining_date]
  end
end

The index name index_employees_on_department_id_designation_and_joining_date will be modified by Rails to idx_on_department_id_designation_joining_date_18832e3a17. The 18832e3a17 are the first 10 letters of SHA256 hexdigest of [:department_id, :designation, :joining_date].

column_names = [:department_id, :designation, :joining_date]

hashed_identifier = OpenSSL::Digest::SHA256.hexdigest(column_names).first(10)

To know more about this feature, please refer to this PR.

Closing Remark

Could your team use some help with topics like this and others covered by ShakaCode's blog and open source? We specialize in optimizing Rails applications, especially those with advanced JavaScript frontends, like React. We can also help you optimize your CI processes with lower costs and faster, more reliable tests. Scraping web data and lowering infrastructure costs are two other areas of specialization. Feel free to reach out to ShakaCode's CEO, Justin Gordon, at justin@shakacode.com or schedule an appointment to discuss how ShakaCode can help your project!
Are you looking for a software development partner who can
develop modern, high-performance web apps and sites?
See what we've doneArrow right