updated in Apr 2022
Hopefully, your builds “just work”, once you have things configured. That’s the intention, but the reality can fall a bit short, so this article talks in detail about some of the limitations that customers run into while building.
The operation of Netlify’s build system is pretty well documented in several places such as:
- a somewhat conversational “how it works” guide.
- our official documentation
- and you can even see the source code, and run yourself, locally, following these instructions.
Today, we’ll talk about why this is a case where size does matter!
Let’s start with the size (memory usage) of your build processes. The reason they matter is that our default build environment is small: we guarantee you only 3GByte of memory and 1 CPU. You can count on that for every build, and you should design your build process to use those benchmarks as a maximum. It is possible that you will sometimes be able to use up to 6Gb as described on our pricing page but that is occasional/lucky, not the norm - act as though you have only 3Gb and your build will always fit.
How can you tell how much memory is used? One way is by using the “local build” process and watching how much memory the docker container itself uses via your local memory profiler of choice (mine is
top(1)) - that will be literally the same thing that we are running on our hardware. You could also limit that container via docker settings to 3Gb to simulate our environment more precisely as a better “test” and less of a monitor. We can’t provide support on how you use docker, but I’m confident you can figure it out
If you try to use more memory, there are a few potential results:
- Your build process will likely abort.
- This might look like a silent failure (logs cut off mid build; build is marked as failure)
- Or perhaps we tell you it got killed:
4:15:11 PM: /usr/local/bin/build: line 34: 1208 Killed hugo --log --templateMetrics
- But most often looks like a failure in some component of the build, such as:
- Rarely, you might get lucky and there will be more room on your build host, so you can use up to 6Gb, and it will Just Work at that level. If it doesn’t abort - congrats! Sometimes good things happen, but sticking to our benchmarks is the best way to guarantee things always work as intended.
There is another frequent failure mode around deploying a successful build. Your script runs and completes successfully. We begin to upload…and never finish:
4:50:11 PM: Build script success 4:50:11 PM: Starting to deploy site from 'public/' 4:50:17 PM: Creating deploy tree asynchronously 4:54:39 PM: 61049 new files to upload
What’s happening here? We have to upload your changed files (please check out this article about what “changed” means, and how to reduce the number of subsequent builds) via our API, and if there are tens of thousands of them, it is quite likely that you won’t be able to complete that in the allocated time (which is 15 to 30 minutes for the whole build + deploy process). Aside from slowing down or potentially blocking your deploys, it’s also a bad experience for your return visitors - they cannot use their local browser cache from last visit for files whose checksum or name has changed in a more recent deploy. I don’t think you really changed 61,000 files in that last deploy with intention - I think you changed a single filename that is included in all files, effectively changing them as well. So, don’t do that :).
If you have a lot of changed files but MAYBE not too many, you may see an error like this happen within your normal build timelimit:
failed during stage 'deploying site': Failed to execute deploy: Error: deploy timed out while waiting to enter states: prepared,ready
…then it’s worth posting a link to your deploy in this thread, to see if we can help you extend that time limit (which is 5 minutes to “wrap things up” after the build completes) to help allow the files to be sent within that default time window I mentioned earlier.