Ruby on Rails: what is ar_internal_metadata metada table

What is ar_internal_metadata?

The ar_internal_metadata table is an essential part of Ruby on Rails, used to track the environment in which our application data resides.

Why does ar_internal_metadata exist?

Introduced in Rails 5, the ar_internal_metadata table helps prevent accidental loss of production data by verifying the environment before running potentially destructive commands.

When running commands such as:

  • rails db:schema:load
  • rails db:reset
  • rails db:drop

The content of ar_internal_metadata is verified and if it indicates that the database is from a production environment, the command will fail with this error:


ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.

If you are sure you want to continue, run the same command with the environment variable:

DISABLE_DATABASE_ENVIRONMENT_CHECK=1

That is good because we could mistakenly run these commands in a production or run them in a development environment that is pointing to a production database.

I know what you’re thinking—we would never do that, right? But in reality, even the most careful developers can make mistakes, so it’s always good to have an extra layer of protection. 😇

How does ar_internal_metadata work?

Rails automatically generates the ar_internal_metadata table with the following structure:

  • keyVARCHAR
  • valueVARCHAR
  • updated_attimestamp
  • created_attimestamp

This table is created or updated after every migration. You can inspect its contents with the by running the following SQL query in rails console:


ActiveRecord::Base.connection.execute("SELECT * FROM ar_internal_metadata;")

It has one row with this structure:


=> [{"key"=>"environment", "value"=>"development", "created_at"=>"...", "updated_at"=>"..."}]

Bonus: changing the table name

If you ever need to change the name used for this table, you can do that with this piece of code:

Rails.application.configure do
  config.active_record.internal_metadata_table_name = 'custom_ar_internal_metadata'  
end

This method is defined the ActiveRecord::ModelSchema module. You can read more about it here:

https://edgeapi.rubyonrails.org/classes/ActiveRecord/ModelSchema.html

Conclusion

While this is a crucial layer of protection, if you absolutely need to run a destructive command, you can bypass the check by setting the environment variable:


DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop


Subscribe to my newsletter!

I share content about Software Development & Architecture, Entrepreneurship and Lifelong Learning

Scroll to Top