My Apps Runtime Limits
Every application deployed via My Apps runs inside a container with defined resource limits. This page documents the current limits so you can design your application accordingly.
Memory limits by runtime
Each runtime type has its own memory allocation. The limit is a hard cap enforced by the container runtime; if your process exceeds it, the OS kills and restarts it.
| Runtime | Language / stack | Memory limit | Memory request |
|---|---|---|---|
| web-runner | Node.js | 2 Gi | 512 Mi |
| python-runner | Python | 1 Gi | 512 Mi |
| wasm-runner | WebAssembly | 512 Mi | 256 Mi |
| golang-runner | Go | 2 Gi | 256 Mi |
| dotnet-runner | .NET / ASP.NET Core | 512 Mi | 256 Mi |
The memory limit is the ceiling. The memory request is the amount of memory the scheduler reserves for your container on the underlying node. Your container can use anywhere between the request and the limit; it is only terminated if it exceeds the limit.
CPU
No CPU limit is enforced on any runtime. Your application can use as much CPU as the underlying node can provide, without being artificially throttled.
The wasm-runner and dotnet-runner each have a CPU request of 25 millicores, which is a scheduling hint rather than a cap. All other runtimes have no CPU request either.
In practice this means a CPU-bound workload can burst freely, but will share node resources fairly with other tenants during periods of high aggregate load.
Request body size
The maximum request body size is 64 MB for all runtimes. This is enforced at the ingress layer, so your application code never sees a request larger than 64 MB. Requests exceeding this limit receive an HTTP 413 response before reaching your process.
If your application needs to handle large file uploads, consider chunked uploads where the client sends smaller pieces sequentially, or use a pre-signed URL pattern with an OSC-hosted object store (such as Garage S3) so the file is uploaded directly to storage rather than routing through your application.
Request timeout
HTTP responses must be sent within 60 seconds. The ingress proxy closes the connection and returns HTTP 504 if your handler does not respond within that window.
If your application performs work that takes longer than 60 seconds (video processing, report generation, data imports), structure it as an async pattern:
- Accept the request and return a job ID immediately (HTTP 202 Accepted).
- Process the work in the background.
- Let the client poll a status endpoint, or deliver the result via a webhook.
This approach works well with My Jobs for background job processing.
Plan-based limits
Resource limits are determined by your application's runtime type, not by your subscription plan. A Node.js app on the Free plan gets the same 2 Gi memory limit as a Node.js app on the Business plan. There are no plan-specific resource tiers for My Apps.
Practical implications by runtime
Node.js (web-runner, 2 Gi): The 2 Gi limit is comfortable for most Express, Fastify, or Next.js applications. Watch for in-memory data accumulation in long-running server processes; streamed responses and pagination keep memory usage predictable.
Python (python-runner, 1 Gi): The 1 Gi limit is sufficient for typical Flask or FastAPI services. If you load large ML models or datasets into memory, measure your process's resident set size locally before deploying — many Python model-serving workloads exceed 1 Gi and are better suited to a dedicated instance from the OSC catalog.
WebAssembly (wasm-runner, 512 Mi): WASM apps tend to have small memory footprints. The 512 Mi limit is not usually a constraint for compiled modules, but note that it also applies to any JavaScript host runtime wrapping the module.
Go (golang-runner, 2 Gi): Go's garbage collector is efficient with heap memory. The 2 Gi limit gives substantial headroom; the lower memory request (256 Mi) means the scheduler places Go containers more aggressively on smaller nodes.
NET / ASP.NET Core (dotnet-runner, 512 Mi): The 512 Mi limit is tight for some dotnet workloads. Keep an eye on the default GC heap size, which the .NET runtime sizes relative to total available memory. If you hit OOM restarts, trim the heap ceiling with the DOTNET_GCHeapHardLimit environment variable via your Parameter Store.
Checking if your app is hitting limits
OOM kills appear in the application logs as an abrupt restart with no preceding error messages — the process simply stops mid-run. To investigate:
- Go to My Apps and check the status column for repeated restarts.
- Ask the AI agent: "Show me the logs for my app called myapp" — look for lines around the restart boundary.
- If logs end abruptly without an exception, an OOM kill is the likely cause.
Request timeouts are easier to spot: the client receives HTTP 504, and your application logs show the handler was still running when the connection dropped.
Related resources
- Managing Custom Apps — Restart, rebuild, HA mode, and logs
- Deploy or Publish Your Application — How to deploy an app on OSC
- Parameter Store — Managing environment variables for your app
- My Jobs — Background job processing for long-running work
- Networking and Tenant Isolation — Platform-wide request and resource limits