Limits
Every figure on this page is enforced by the platform. Where a limit depends on your plan, the plan column says so.
Builds
| Limit | Value | What happens |
|---|---|---|
| Duration | 20 minutes | The build is stopped and the deployment fails with "the build ran out of time (20 minutes)". A build that runs this long is stuck — a working storefront build finishes in single-digit minutes. |
| Retries | none | A failed build is not retried. Fix the cause and deploy again. |
| CPU | 7 vCPU, dedicated | The build has a node to itself. |
| Memory | 12 GiB | Node exits with a heap error. The build runs with --max-old-space-size=8192. |
| Project bundle | 100 MB, uncompressed | The deployment is refused before anything is uploaded, and its error states the bundle's size. Contact Laioutr support. |
| Concurrent builds | 1 per platform | A second build waits until the first finishes. It is not queued on a node, so it costs nothing while it waits. |
| Log size | 5 MB | The rest of the log is cut, with a marker at the end. |
| Log retention | 7 days after the build ends | The deployment API answers with an empty log after that. Logs are archived when the build finishes; the build's own pod is removed an hour after it ends. |
| Dependencies | installed fresh | Every build downloads every dependency. The bundle carries no lockfile, so a build can resolve newer versions than the last one. |
| Bundle retention | 7 days | The uploaded project is deleted. It is read once, by the build, so nothing afterwards depends on it — a rollback re-promotes a built image and never rebuilds. |
A build runs on its own node, which is destroyed when the build ends. It reaches the internet the way
a build does anywhere else — your own registry, a Git dependency, a postinstall script that fetches
a prebuilt binary all work. It cannot reach anything inside the platform: no other tenant, no node, no
metadata service.
Your environment variables are readable by everything that runs during the build, including the install scripts of every package you depend on. That is true of every build platform. Give a build only the credentials it needs.
Running storefronts
A size class fixes the shape of one pod. On M and L, how many pods you get follows from the page views your plan covers, so a larger plan on the same class means more pods, not bigger ones. S is one size whatever its page views: two pods, and a third under load.
On M and L, up to a few million page views a month the minimum of three pods already covers the traffic. Above it the count grows with your allowance.
| S | M | L | |
|---|---|---|---|
| CPU reserved | 0.5 vCPU | 1 vCPU | 1 vCPU |
| CPU ceiling | 2 vCPU | 2 vCPU | 2 vCPU |
| Memory reserved | 768 MiB | 768 MiB | 1536 MiB |
| Memory ceiling | 2 GiB | 2 GiB | 3 GiB |
| JavaScript heap | 1,536 MiB | 1,536 MiB | 2,304 MiB |
| Writable disk | 1 GiB | 1 GiB | 2 GiB |
| Adds pods under load | one, up to 3 | yes | yes |
| Preview deployments awake at once | 5 | 5 | 10 |
S adds one pod under load, never more. A spike beyond three pods makes an S storefront slower and never more expensive. M and L add pods up to a ceiling derived from your page-view allowance.
An S storefront runs at least 2 pods, M and L at least 3, and the platform spreads them across separate machines wherever the cluster has machines to spread them over.
The JavaScript heap is 75 % of the memory ceiling; the rest is for Node itself. A storefront that
outgrows it stops with JavaScript heap out of memory and restarts.
Environments
Every environment other than production runs as a storefront of its own, on the class Laioutr chooses for it. It has the pod of S, adds no pods under load, and keeps one preview awake at once. While nobody visits it runs no pod at all: after 5 minutes without a request it sleeps, and the next request waits for it to start — about 4 seconds. An environment whose pod cannot start answers like a preview beyond the awake cap: it waits about 60 seconds and then gets 504. Its hostname is never indexed. The class cannot be changed, and environments are part of your license rather than billed by page view.
Per request
| Limit | Value | What happens |
|---|---|---|
| Request timeout | 125 seconds | The edge answers 524. Anything that takes longer belongs in a background job. |
| Request body | 100 MB | The edge answers 413 before the request reaches your storefront. Send large uploads from the browser straight to a storage service of your own. |
| Streams and WebSockets | 300 seconds | The connection closes. Reconnect from the client. |
| Startup | 120 seconds | A pod that has not answered its health check by then is restarted. At build time the limit is 60 seconds, and the deployment fails. |
| Rate limit | per hostname, about 370 requests a minute for each pod your plan can run at most, rounded up to the next hundred | 800 a minute for an S storefront on two pods, 1,200 for a storefront of at most three, 400 for an environment, and 400 for each deployment's own hostname. Requests over it get 429. It sits at about twice what those pods can serve, so ordinary traffic never reaches it. Each hostname counts on its own: the platform hostname, each of your domains and each deployment's hostname has its own limit, so a test run against a preview never uses up production's. On a production hostname, requests for your build's own files under /_nuxt/ count against a second limit of the same size. Every request that reaches your storefront on one hostname counts, whoever sends it, so one client sending too fast — a scraper, a load test — uses it up for every visitor of that hostname. Responses the edge serves from its cache do not count. Two gateways each allow half, so a burst that lands mostly on one of them meets the limit slightly early. |
| Shutdown grace | 60 seconds | A request in flight while a pod is replaced gets this long to finish; a longer one is cut. |
Outgoing requests
Your storefront can reach any public address. Pods on one machine share its outgoing IP address, so an upstream API that limits requests per IP counts your storefront together with others on the same machine. A fixed outgoing address is not available yet.
Configuration
There are no runtime environment variables. Your project's configuration is built into the image, so changing a value means a new deployment.
Storage and state
Write only to /tmp, and only as a scratch space. The writable disk in the table above is the
ceiling; a pod that exceeds it is evicted. Nothing written by a storefront survives a restart, and
pods are replaced routinely. The platform provides no file storage, so keep files in a service of your
own.
The shared cache is a cache. It is one instance shared by every storefront on the platform, so an entry can be evicted at any time to make room for new ones, yours or another storefront's, and how long an entry stays depends on their traffic as well as yours. The cache starts empty after a restart. Never keep state there that you cannot rebuild.
The shared cache has two size limits.
| Limit | Value | What happens |
|---|---|---|
| One entry | 8 MB | The cache refuses the write and closes the connection, which the storefront reopens. That entry is never cached, so every request for it is a miss. Cache smaller pieces. |
| Replies waiting on one connection | 64 MB at most, or 32 MB for 60 seconds | The cache closes the connection, which the storefront reopens. Reads in flight on it fail. Read fewer or smaller entries at once. |
A storefront cannot create a load balancer, open a node port, or claim a disk. Those are billable resources, and the platform creates none of them on your behalf.
Hostnames
Every storefront gets a permanent hostname of the platform's own from the day it is created,
<name>.laioutr.app, and that hostname serves production whether or not you have connected a domain.
Laioutr assigns the name when the storefront is created and keeps it for good, also when the project is
renamed. Once one of your own domains is canonical, the platform hostname answers
X-Robots-Tag: noindex, so the two never compete for the same content in search results.
Preview deployments
Every deployment has a hostname of its own, <name>-<9 characters>.laioutr.app, for as long as it is
kept. A deployment that is no longer kept answers with a not-found page.
| Kept | For how long |
|---|---|
| Production deployments you replaced | the last 2, for 24 hours — the window for a rollback without a rebuild |
| Previews | the newest deployment of each preview name, until a newer one of that name replaces it |
| All previews together | at most 10; the oldest goes first |
Rotating your project's content preview token withdraws the production deployments you replaced at once: none of them can be made live again without a new build.
A preview that nobody visits scales to zero after 5 minutes and wakes on the next request, so the first request to a cold preview is slower. Beyond the number of previews awake at once in the table above, a request to another preview waits about 60 seconds and then gets 504, until one of the awake previews sleeps. A preview whose pod cannot start answers the same way. Preview hostnames are never indexed.
Password protection
| Limit | Value | What happens |
|---|---|---|
| Passwords | one per project | A new password replaces the old one and logs out everyone who used the old one. |
| Bypass secrets | 20 per project, the Laioutr Studio secret included | Creating another is refused. Revoke one you no longer use. |
| Login lifetime | 7 days | The visitor enters the password again. |
| Password attempts | 10 per minute per IP address and hostname | 429, and the page says to wait until the minute ends. The count is kept per Cloudflare location. |
| Time for a change to take effect | up to 60 seconds | A removed password or a revoked bypass secret still works until then. |
| Apex hostnames | cannot be protected | The apex redirects to www; protect that hostname. |
| Previews | protected by default | Switch preview protection off for the environment, or send a bypass secret. |
A protected hostname that cannot be checked — for example while the platform's protection store is unreachable —
answers 503 with Retry-After. It never falls back to serving the page unprotected.
Password protection explains how to set it up.
Metrics
Your storefront's own metrics — the HTTP, Node.js runtime and Laioutr metrics it sends over OpenTelemetry — and a copy of its traffic and container metrics are kept per environment: production and each other environment of your project count separately. The platform keeps its own record for billing separately; nothing on this page changes what you are billed.
The copy of your traffic and container metrics counts against the same series, sample and label limits as
your own metrics. The platform also adds labels to every series your storefront sends — tenant,
deployment, service, job, instance, and the instrumentation scope's otel_scope_name and
otel_scope_version — and the metric name counts as a label too, so at least 22 of the 30 labels are left
for your own attributes.
| Limit | Value | What happens |
|---|---|---|
| Metric names | http.server.*, http.client.*, nodejs.*, v8js.*, laioutr.*, orchestr.* | Any other metric your code sends is dropped before it is stored. Rename a metric you need into one of these prefixes, or stop sending it. |
| Active series | 150,000 | New series are refused; series that already exist keep updating. Each pod writes its own series, and a replaced pod's series count for a few hours. A label with unbounded values — a URL, an id, anything a visitor sends — is the usual cause: remove it, or replace it with a small set of values such as the route. |
| Samples | 10,000 per second, bursts to 200,000 | Samples over the rate are dropped until the rate drops, including a backlog sent after an outage of ours. Samples more than 6 hours older than the newest your environment has sent are refused whatever the rate. Export less often, or send fewer series. |
| Labels per series | 30, including the metric name and the platform's labels | The series is refused. Drop attributes you do not query. |
| Label value length | 512 characters | The series is refused. Shorten the value; a value this long usually should not be a label at all. |
| Retention, standard | 5 days | Older data is deleted. Deletion works on whole days of data, so data is kept at least 5 days and up to about 2 more. For longer, contact Laioutr support about extended observability. |
| Retention, extended observability | 30 days | As above. Laioutr support moves an environment between tiers. Moving to extended keeps what is still there; days already deleted do not come back. Moving back to standard deletes everything older than 5 days within about a day. |
| After the environment is removed | up to about 32 days | The metrics are deleted. |
Logs
Your storefront's own logs — what its pods and builds write — are kept per environment, and so is a copy of the access log for your hostnames. The visitor's IP address is not in that copy.
| Limit | Value | What happens |
|---|---|---|
| Log volume | 2 MB per second, bursts to 4 MB | Lines over the rate are dropped until it falls. Other environments and projects are not affected. Log less: leave debug output off in production. |
| One output stream | 1 MB per second, bursts to 4 MB | Lines over the rate are dropped. A container's standard output and standard error are limited separately, so a single noisy container is limited before the whole environment is. |
| Log streams | 1,000 | New streams are refused. A stream is the standard output or the standard error of one container in one pod, and a restarted container starts new ones. The platform sets a stream's labels, so the count follows your pods: fix a container that restarts again and again. |
| Line length | 64 KB | Longer lines are cut, not dropped. Split a large payload over several lines. |
| One log call | 16 KiB of its message | The rest is cut, and the log view marks the entry as cut. Logs says what one entry holds. |
| Retention, standard | 5 days | Older logs are deleted. Deletion works on whole days, so logs are kept at least 5 days and up to about 1 more. For longer, contact Laioutr support about extended observability. |
| Retention, extended observability | 30 days | As above. Moving between tiers works as for metrics. |
| After the environment is removed | up to about 31 days | The logs are deleted. |
Suspension
A suspended storefront keeps its hostnames and its images, answers every request with a holding page, and runs no pods. Nothing is deleted.
Laioutr Cloud
Laioutr Cloud is the built-in hosting and delivery environment for frontends created with Laioutr. It provides a ready-to-use infrastructure layer, so you can launch and operate your storefront without having to set up your own hosting, deployment pipelines, or runtime configuration.
Fair use
What Laioutr Cloud expects of a storefront beyond its enforced limits — monthly allowances per size class, what must never be served, and what happens when a storefront goes beyond them.