What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Add a database index in Rails when a recurring query or an integrity rule gives you a specific reason—not simply because a column appears in a query. Indexes can speed up row lookups, but they also add work and storage costs to the database. Use Rails migrations to define the index, then inspect the database’s query plan and workload to see whether it helps.

What a database index does—and what it costs

An index is a data structure the database can use to locate rows without examining the whole table in the same way as an unindexed lookup. PostgreSQL’s documentation sums up the trade-off: “An index allows the database server to find and retrieve specific rows much faster than it could do without an index. But indexes also add overhead to the database system as a whole, so they should be used sensibly.” PostgreSQL 18: Indexes

The benefit is faster retrieval for queries that can use the index. The cost is additional work for the database system, including maintaining indexes as data changes. There is no universal speedup figure: the result depends on the query, data, database engine, and workload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When should you add an index in Rails?

Start with a recurring query or a database integrity requirement. Look at the query’s filters and sort order, then examine the plan the database chooses. An index is a candidate to test, not a guarantee of improvement: the optimizer may choose another plan, and a faster read can come with costs elsewhere in the workload.

  • Frequent lookup or filtering: Consider an index on the columns used to find the relevant rows.
  • Filtering and sorting together: Consider a composite index only when its column order fits the actual query patterns. Column order is meaningful; a composite index is not a set of interchangeable single-column indexes.
  • Uniqueness: Use a unique database index when the database must prevent duplicate values.
  • Search or specialized access: Choose an index method that matches the search and is supported by your database adapter.

Do not index every queried column by default. Check the plans for representative queries and consider the broader workload, including writes and index maintenance. PostgreSQL 18 index guidance and the Rails 8.1 Active Record Query Interface guide explain the trade-off and plan inspection.

How to add an index in a Rails migration

Rails migrations provide add_index for a single column or an array of columns. The following examples use the Rails 8.1 migration class syntax; check the syntax and option support for your app’s Rails version and database adapter.

Single-column and composite indexes

class AddIndexesToOrders < ActiveRecord::Migration[8.1]
  def change
    add_index :orders, :customer_id
    add_index :orders, [:customer_id, :created_at]
  end
end

The single-column index is a candidate for queries that filter on customer_id. The composite example may fit queries that filter by customer and use creation time, but its usefulness depends on the predicates and ordering in the actual workload. Verify the plan rather than assuming either index will be used.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Enforcing uniqueness

add_index :users, :email, unique: true

A unique index is a database-level integrity rule as well as an access path. Application validations alone cannot guarantee uniqueness in every circumstance. Before adding one, check existing rows for duplicates and coordinate the constraint with the application’s validation and error-handling behavior. Rails’ migration guidance discusses database-level unique indexes and foreign keys as stronger integrity enforcement. Rails Active Record Migrations guide

PostgreSQL concurrent creation

For PostgreSQL, Rails supports algorithm: :concurrently when creating an index. Concurrent index creation cannot run inside a transaction, so disable the migration’s DDL transaction:

class AddIndexToOrdersOnCustomerId < ActiveRecord::Migration[8.1]
  disable_ddl_transaction!

  def change
    add_index :orders, :customer_id, algorithm: :concurrently
  end
end

This option is PostgreSQL-specific, not a portable instruction for every Rails database. Check the behavior for your Rails and adapter versions and account for the migration’s production deployment implications. Rails documents the algorithm option in its Rails 8.0 add_index API and the transaction restriction in its migration guidance.

How to check whether the database uses the index

Active Record’s .explain shows the database plan for a relation. Inspect a query shaped like the one your application actually runs:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Order.where(customer_id: 42).order(:created_at).explain

For PostgreSQL, Rails also documents analysis options such as:

Order.where(customer_id: 42).order(:created_at).explain(:analyze, :buffers)

Options such as :analyze execute the query to gather measurements; choose a suitable query and environment before using them. Rails documents analysis support and engine-specific differences for PostgreSQL, MySQL, and MariaDB in its Active Record Query Interface guide and Active Record and PostgreSQL guide.

A plan is evidence about that query and the data available when the plan was produced. It does not prove that the index will always be selected or improve the complete workload. Compare representative query behavior and consider write activity and index maintenance alongside read performance.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Which index option fits the query?

Choose the index shape from the access pattern, integrity need, database support, and deployment conditions. Rails exposes options for several index features, but availability and behavior vary by adapter.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Single-column index: A straightforward candidate for a recurring lookup or filter on one column.
  • Composite index: A candidate when queries use multiple columns together. Match the column order to real predicates and ordering; validate with a plan.
  • Unique index: Appropriate when the database must enforce that indexed values are unique.
  • Partial index: Rails documents support for PostgreSQL and SQLite. It indexes rows matching a condition, so confirm that the target query and adapter support align.
  • Included columns: Rails documents included columns for PostgreSQL only. PostgreSQL can make included values available to index-only scans without using those columns as search keys.
  • Index method: The available methods depend on the adapter. PostgreSQL’s guide, for example, describes GIN-based examples for full-text search; do not treat PostgreSQL-specific methods as portable Rails options.

Rails documents the add_index options and adapter qualifications in its Rails 8.0 API reference. PostgreSQL’s Rails and PostgreSQL guide describes PostgreSQL-specific index features.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.