If you see this warning regularly and worry that your application may soon fail to deploy, then this article is for you.
Warning: You slug size (443 MB) exceeds our soft limit (300 MB) which may affect boot time
First things first, what is a slug?
A slug is essentially the compressed copy of your application comprising of your git repo along with packages that are installed at deploy time like gems, node_modules, etc. The maximum allowed slug size (after compression) is 500MB. Applications using multiple buildpacks especially can strain this limit.
The first and foremost thing we need to do is determine which files/folders are taking up the maximum space on the dyno. Heroku has documented the command for doing just that but it doesn’t display hidden files.
It is crucial that you take hidden files into account due to the following reasons:
- You could have hidden files/folder as part of your repository.
- apt-based dependencies installed using
heroku-buildpack-aptare stored in the hidden folder
- The buildpacks- ruby, python are installed in the hidden folder
If we are using multiple buildpacks, then it’s possible that the buildpacks themselves are consuming a major chunk of the slug size.
Let’s check who is consuming the maximum space from one of our applications-
# du -sh .[^.]* * | sort -hr >> 216M node_modules 188M vendor 76M tmp 38M bin 16M public 1.5M app 372K yarn.lock 236K test 196K config 108K db 32K lib 16K .heroku
The immediate steps we can take is to start by ignoring files from the repository that are not required to run the app. We do this by specifying the name of the top-level folders inside the file .slugignore
# cat .slugignore /test /spec /docs
Next, we can ignore any bundler groups that are not needed
for the environment running our application.
test group are excluded by default, but if
we are using any custom groups like
docker, we can exclude it
by adding it to the environment variable
heroku config:set BUNDLE_WITHOUT="development:docker:test"
node_modules and other artifacts
Even though the first two steps helped in reducing the slug size,
they didn’t make much of a difference. What really helps is
node_modules folder after compilation but right
before the slug is generated.
All that is needed is to add the below file to enhance the
rake task to run the rake task for removing the
# cat lib/tasks/assets.rake # Adapted from https://github.com/heroku/heroku-buildpack-ruby/issues/792 namespace :assets do desc "Remove 'node_modules' folder" task rm_node_modules: :environment do Rails.logger.info "Removing node_modules folder" FileUtils.remove_dir("node_modules", true) end end skip_clean = %w(no false n f).include?(ENV["WEBPACKER_PRECOMPILE"]) unless skip_clean if Rake::Task.task_defined?("assets:clean") Rake::Task["assets:clean"].enhance do Rake::Task["assets:rm_node_modules"].invoke end else Rake::Task.define_task("assets:clean" => "assets:rm_node_modules") end end
assets:clean on every deploy so we don’t need to manually do anything on top of this.
This simple technique resulted in following reduction in one of our smaller Apps-
# du -sh node_modules 247M node_modules # Slug size before -----> Compressing... Done: 104M # Slug size after -----> Compressing... Done: 79.4M