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
Slug
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.
Using slugignore
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-apt
are stored in the hidden folder.apt
- The buildpacks- ruby, python are installed in the hidden folder
.heroku
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.
The development
and 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 BUNDLE_WITHOUT
.
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
removing the 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 assets:clean
rake task to run the rake task for removing the node_modules
folder.
# 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
heroku-buildpack-ruby
autoruns
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