Edgio Platform Limits
This guide describes caveats and limits of Edgio platform as applied to all projects running on it.
Legend
Kb
stands for kilobytes and means 1,024 bytes (2^10 bytes)Mb
stands for megabytes and means 1,024 kilobytes (2^20 bytes)Gb
stands for gigabytes and means 1,024 megabytes (2^30 bytes)
Request and Response Limits
Type | Limit | Description |
---|---|---|
Response time from origin server | 60 seconds | The maximum number of seconds that Edgio will wait for a response from an origin server (e.g., your web server). The response for a request that exceeds this limit is a 531 Project Upstream Connection Error . Requests that exceed this limit should return a 536 Project HTTP Response Timeout. We will update our service to return this status code instead of a 531 Project Upstream Connection Error response in the near future. |
Response body size from static | 2Gb | The maximum size of a response body of Edgio static assets. |
Response body size from custom origin | 2Gb | The maximum size of a response body from a custom origin. |
Response body size from Edgio serverless | 6Mb | The maximum size of a response body from Edgio serverless. |
Path and query string size | 8Kb | The maximum bytes (not characters) that Edgio will accept in path and query string. |
Cookie size | 32Kb | The maximum bytes that Edgio will accept in request or response cookies. |
HTTP header size | 64Kb | The maximum bytes that Edgio will accept in request or response HTTP headers. |
HTTP header count | 70 | The maximum number of developer-controlled headers Edgio will accept in HTTP request or response. Exceeding this will result in 542 status code. |
Scheduling timeout | 60 seconds | The number of seconds Edgio will try to schedule a request processing before timing out. Exceeding this will result in 541 status code. |
Worker timeout | 20 seconds | The number of seconds Edgio will wait for project code to process the request before timing out. Exceeding this will result in 539 status code. |
Prerender concurrency | 200 | |
Total number of prerendered requests | 25,000 per deployment | |
Maximum number of nested requests | 3 | “Nested” means an Edgio site is the upstream of itself or of another Edgio site. Exceeding this will result in 538 status code. |
Access Logs
Value | Limit | Description |
---|---|---|
Size | Unlimited | All access logs will always be logged. |
Time | 2 hours | The minimum time that Edgio guarantees that access logs will be available for reading. |
Prohibited Headers
The following is a list of headers that cannot be modified by your project code. These values are immutable and can only be set by the Edgio platform.
x-0-platform
x-0-version
x-0-t
x-0-components
x-0-status
host
x-request-id
content-length
via
Serverless Bundle Size
Edgio has a serverless bundle limit for your project of 50 MB (250 MB uncompressed). If your deployment to Edgio fails due to exceeding the bundle limit, you will see the following error message:
12022-08-08T13:47:13Z - internal error - Error in xdn-deploy-lambda: Your production build exceeds the maximum allowed size of 50 MB (compressed) / 250 MB (uncompressed).2The current size is 51.19 MB (compressed).3Please ensure that list of dependencies in package.json contains only those packages that are needed at runtime.4Move all build-time dependencies such as webpack, babel, etc... to devDependencies, rerun npm | yarn install, and try to deploy again.
Following are the possible fixes that would help you reduce serverless bundle size by better engineering. If none of these does it, feel free to raise an issue on Edgio Forums.
Possible Fix [1]: Segregating devDependencies from dependencies
Typically, this is due to node_modules marked as
dependencies
when they are more appropriate in devDependencies
within the package.json
file. Modules marked as dependencies will be included in the serverless bundle. Dev-only modules such as babel
, jest
, webpack
, etc. should be moved to devDependencies
as shown:Diff
1"dependencies": {2 "@nuxtjs/sitemap": "2.4.0",3 "@nuxt/core": "2.15.7"4- "babel": "7.12.7",5- "jest": "28.1.3"6+ },7+ "devDependencies": {8+ "babel": "7.12.7",9+ "jest": "28.1.3"10}
Possible Fix [2]: Segregating assets from serverless bundle
Additionally, this can be related to assets (such as fonts or images) that are imported into your project code. These resources are typically better referenced as static assets which are stored outside of the serverless bundle.
You can remedy this by creating a
public
directory in the root of your project. Move all of your font and image assets to this path. Then, create a route in routes.js
to serve those requests as static assets using the following as an example:JavaScript
1router.get('/assets/:path*', ({ serveStatic }) => {2 serveStatic('public/:path*')3})
Now, you can update your code references from importing the assets to referencing the static path, such as:
Diff
1- import myImage from 'public/images/Image1.png'2...3- <div><img src={myImage}/></div>4+ <div><img src="/assets/images/Image1.png"/></div>
Possible Fix [3]: Computing which node_modules be included in the serverless bundle
It might be possible, that Possible Fix [1] reduces your serverless bundle size, but not reduce it to less than 50 MB (250 MB Uncompresssed). Another way to identify which dependencies would be required in the runtime is to use
@vercel/nft
package (a “Node.js dependency tracing utility”).Step 1. Install
@vercel/nft
as devDependency:Bash
1npm i -D @vercel/nft
Step 2. Create a file named
setNodeModules.js
in the root directory of your project with the following code:JavaScript
1const fs = require('fs')2const { nodeFileTrace } = require('@vercel/nft')34const setNodeModules = async () => {5 // Enter an entry point to the app, for example in Nuxt(2), the whole app inside core.js6 const files = ['./node_modules/@nuxt/core/dist/core.js']7 // Compute file trace8 const { fileList } = await nodeFileTrace(files)9 // Store set of packages10 let packages = {}11 fileList.forEach((i) => {12 if (i.includes('node_modules/')) {13 let temp = i.replace('node_modules/', '')14 temp = temp.substring(0, temp.indexOf('/'))15 packages[`node_modules/${temp}`] = true16 } else {17 packages[i] = true18 }19 })20 // Sort the set of packages to maintain differences with git21 fs.writeFileSync(22 './getNodeModules.js',23 `module.exports=${JSON.stringify(24 Object.keys(packages)25 .sort()26 .reduce((obj, key) => {27 obj[key] = packages[key]28 return obj29 }, {})30 )}`31 )32}3334setNodeModules()
Step 3. Change your existing
package.json
to have node setNodeModules.js
before each command as follows:Diff
1- "layer0:dev": "layer0 dev",2- "layer0:build": "layer0 build",3- "layer0:deploy": "layer0 deploy"45+ "layer0:dev": "node setNodeModules.js && layer0 dev",6+ "layer0:build": "node setNodeModules.js && layer0 build",7+ "layer0:deploy": "node setNodeModules.js && layer0 deploy"
Step 4. Change your
layer0.config.js
to have:JavaScript
1// https://docs.layer0.co/applications/layer0_config2module.exports = {3 includeFiles: require('./getNodeModules'),4}
Edgio Platform Caveats
NodeJS native extensions
In a lof of scenarios, NodeJS native extensions might be required to perform specific tasks related to your application.
For example, you might need to use OpenCV to perform some checks on an image before making it publicly available.
Or you might need to use extensions like
node-microtime
for finer-grained performance analysis.When Edgio bundles your application for deployment, we also do some “tree-shaking” to remove unnecessary files in your build.
This makes the bundle size smaller and more efficient to load on our serverless platform during a cold-start.
But it could have unintended consequences where we might strip away native extension binaries required for your
application to function.
If that is the case, you might encounter an error like the following when trying to use modules that depend on the native binaries.
1Error: No native build was found for runtime=node abi=83 platform=linuxglibc arch=x642at Function.load.path (/var/task/node_modules/microtime/node_modules/node-gyp-build/index.js:59:9)3at load (/var/task/node_modules/microtime/node_modules/node-gyp-build/index.js:19:30)4at Object.<anonymous> (/var/task/node_modules/microtime/index.js:1:43)5at Module._compile (internal/modules/cjs/loader.js:1085:14)6at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)7at Module.load (internal/modules/cjs/loader.js:950:32)8at Function.Module._load (internal/modules/cjs/loader.js:790:12)9at Module.require (internal/modules/cjs/loader.js:974:19)10at require (internal/modules/cjs/helpers.js:101:18)11at Object.<anonymous> (/var/task/node_modules/broadcast-channel/dist/es5node/methods/node.js:57:41)
To fix this issue, you need to instruct Edgio to include the binary files that your application requires.
This can be done by using the
includeFiles
property in layer0.config.js
like so:JavaScript
1includeFiles: {2 'node_modules/microtime/**/*': true,3},
Or you could choose to bundle everything in the packages listed in the
dependencies
property of package.json
by using
includeNodeModules
property.Readonly filesystem in serverless runtime
Web developers often use the filesystem as a temporary data source for their applications. That includes creating and/or
manipulating files based on user requests. For example, storing user uploaded files locally and stripping metadata
before proceeding. But this can open up security vulnerabilities where a bug in the application can be used to modify
the application itself.
So, as a best practice Edgio App Platform does not allow you to change the content of application files on
the filesystem during runtime. If you need to modify an application file, you must make those changes locally and make
a new deployment. This limits the attack surface of your potential application vulnerabilities. It also allows us to
make your application more distributed and resilient to outages. Edgio takes your application code and
deploys it to multiple regions with a read-only filesystem. This way, if the primary availability zone or region is
unavailable, your application will still be accessible from another region.
Edgio App Platform runs your application in
/var/task
directory. If you attempt to write a file in that
directory, you may come across an error like the following:1EROFS: read-only file system, open '/var/task/temp-upload.jpg'
To resolve issues like this you can use “tmp” directory to store any temporary files. But this directory might be
different on you local environment vs Edgio serverless runtime. So, following is a good way to write code
that will work on your local machine as well as Edgio serverless runtime.
JavaScript
1import { tmpdir } from 'os';2import * as path from 'path';3const tmpFilePath = path.join(tmpdir(), 'temp-upload.jpg');
Another thing to keep in mind is that “tmp” directory is ephemeral, meaning that it gets reset/recycled. If you store a
file in “tmp”, it most likely won’t be available in the next request. That’s why you’ll need to use external services
to store permanent file storage. These external services can be Amazon S3, Google Cloud Storage, or any other storage.