Failure to push to Heroku with Ruby on Rails and SQLite3 native extension

Every once in a while I read questions on StackOverflow like this one where the developer is unable to deploy a Rails application to Heroku due to some error related to the sqlite3 library.

The error, in general, looks like the following one

remote:        Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
remote:        
remote:        /tmp/build_1933bfd027d23ded5c4a036825ecff71/vendor/ruby-2.0.0/bin/ruby extconf.rb
remote:        checking for sqlite3.h... no
remote:        sqlite3.h is missing. Try 'port install sqlite3 +universal',
remote:        'yum install sqlite-devel' or 'apt-get install libsqlite3-dev'
remote:        and check your shared library search path (the
remote:        location where your sqlite3 shared library is located).
remote:        *** extconf.rb failed ***
remote:        Could not create Makefile due to some reason, probably lack of necessary
remote:        libraries and/or headers.  Check the mkmf.log file for more details.  You may
remote:        need configuration options.
remote:        
remote:        Provided configuration options:
remote:        --with-opt-dir
remote:        --without-opt-dir
remote:        --with-opt-include
remote:        --without-opt-include=${opt-dir}/include
remote:        --with-opt-lib
remote:        --without-opt-lib=${opt-dir}/lib
remote:        --with-make-prog
remote:        --without-make-prog
remote:        --srcdir=.
remote:        --curdir
remote:        --ruby=/tmp/build_1933bfd027d23ded5c4a036825ecff71/vendor/ruby-2.0.0/bin/ruby
remote:        --with-sqlite3-dir
remote:        --without-sqlite3-dir
remote:        --with-sqlite3-include
remote:        --without-sqlite3-include=${sqlite3-dir}/include
remote:        --with-sqlite3-lib
remote:        --without-sqlite3-lib=${sqlite3-dir}/
remote:        
remote:        
remote:        Gem files will remain installed in /tmp/build_1933bfd027d23ded5c4a036825ecff71/vendor/bundle/ruby/2.0.0/gems/sqlite3-1.3.11 for inspection.
remote:        Results logged to /tmp/build_1933bfd027d23ded5c4a036825ecff71/vendor/bundle/ruby/2.0.0/gems/sqlite3-1.3.11/ext/sqlite3/gem_make.out
remote:        An error occurred while installing sqlite3 (1.3.11), and Bundler cannot
remote:        continue.
remote:        Make sure that `gem install sqlite3 -v '1.3.11'` succeeds before bundling.
remote:  !
remote:  !     Failed to install gems via Bundler.
remote:  !     
remote:  !     Detected sqlite3 gem which is not supported on Heroku.

This "issue" has been around for a very long time, my oldest answer I was able to find is dated October 2010. Since this is a very common question on StackOverflow, I decided to write a small tutorial to explain how to proceed.

The root cause is the default Ruby on Rails configuration for new projects that assumes you will be using SQLite as a database. However, Heroku doesn't allow you to use SQLite and requires you to use PostgreSQL insted.

Although the use of PostgreSQL is suggested in the Heroku "getting started with Rails 4" article, this question is still very popular on StackOverflow among Ruby on Rails beginners, due to the amount of tutorials available online that mention the deploy of an app to Heroku without properly highlighting this caveat.

Luckily, this is very easy to fix. You simply need to replace the SQLite 3 gem with the PostgreSQL gem in your Gemfile.

# replace gem "sqlite3" with
gem "pg"

You can also keep using SQLite in development and test, and switch to PostgreSQL only for production. However, I strongly advice you against this approach for the following reasons:

  1. In general, it is recommended that your production environment matches as close as possible your development and testing environments, otherwise you may not be able to catch bugs and side effects that will likely show up in production
  2. Even if you use two configurations, unless you use the $ bundle --without development test syntax, your Gemfile.lock will still bundle the SQLite gem and the deployment to Heroku will fail.

If you feel you want to proceed down this path, here's an example of the configuration you can use

group :production do
  gem "pg"
end

group :development, :test do
  gem "sqlite3"
end

The same issue was used to be reported with several different messages at Heroku during all these years. Here's another one:

   An error occurred while installing sqlite3 (1.3.10), and Bundler cannot continue.
   Make sure that `gem install sqlite3 -v '1.3.10'` succeeds before bundling.
 !

 !     Failed to install gems via Bundler.
 !     
 !     Detected sqlite3 gem which is not supported on Heroku.
 !     https://devcenter.heroku.com/articles/sqlite3
 !

 !     Push rejected, failed to compile Ruby app