Home / OCI

OCIHow-toIntermediate

Optimization: OCI Functions cold starts, memory sizing and provisioned concurrency

OCI Functions can take seconds on the first call after idle, which hurts APIs behind API Gateway. Measure cold starts, shrink images and start-up work, size memory deliberately, use provisioned concurrency only for latency-sensitive functions, and tune timeouts and invocation patterns.

Deepak Bhardwaj3 min read

Applies toOCI Functions (Fn Project based), API Gateway function backends, Events/Connector Hub triggers, OCI Container Registry

Symptom

An HTTP endpoint backed by a function returns in 200 ms most of the time, but the first request after a quiet period takes several seconds. Event-driven functions are fine; user-facing ones aren't.

1. Measure

  • Function metrics (oci_faas namespace): FunctionInvocationCount, FunctionExecutionDuration, FunctionResponseCount by status.
  • API Gateway metrics and access logs: latency percentiles per route.
  • Compare p50 vs p99 latency; a large gap at low traffic is typically cold starts.

2. Make start-up cheaper

Cause Fix
Large container image Slim base images (FDK images), remove build tools, multi-stage builds
Heavy initialisation per call Initialise SDK clients and config once (outside the handler)
Big language runtimes/frameworks Lighter frameworks; Java: consider GraalVM native images where supported
Fetching secrets on every call Cache with a TTL inside the container
Image pulled from a far region Keep OCIR repository in the same region as the function

Image size has a direct effect on cold start time. Check it in OCIR and aim to shrink it.

3. Size memory

Functions are configured with a memory limit (128 MB up to the service maximum), and CPU share follows memory. Too little memory slows CPU-bound code and start-up, and too much costs more per second. Test a few sizes with realistic payloads:

fn update function orders-app enrich-order --memory 512
fn invoke orders-app enrich-order < sample.json

Billing is based on memory × execution time (GB-seconds) plus invocations, so faster at a bigger size can cost the same or less.

4. Provisioned concurrency for latency-sensitive functions

Provisioned concurrency keeps a number of function instances ready, which removes cold starts for that capacity. It's billed for as long as it's configured. Set it on the function (console, CLI or Terraform) in provisioned concurrency units, sized to typical concurrent requests:

oci fn function update --function-id $FN \
  --provisioned-concurrency '{"strategy": "CONSTANT", "count": 20}'

Check the units and minimums in the current docs. Use it only for user-facing paths, and leave background functions on demand.

5. Timeouts and invocation patterns

  • Timeout close to real p99 duration (not the maximum "just in case").
  • For long work, use detached (asynchronous) invocation or move it to a container instance/job.
  • Batch events where possible instead of one invocation per tiny event.
  • API Gateway caching for identical GET requests.

6. Watch concurrency limits

Functions have tenancy/application limits on concurrent memory. A spike in one function can throttle others in the same application. Separate noisy functions into their own application and request limit increases ahead of known peaks.

7. Track it

Metric Before After
API p99 latency
Image size
Average duration and memory
Monthly Functions cost

Tip

If one function serves a public API and the rest process events, give the API function its own application with provisioned concurrency. Event processors keep the pay-per-use model.

Checklist

  • Cold starts identified (p99 vs p50, low-traffic periods)
  • Image size and initialisation reduced
  • Memory tested at several sizes
  • Provisioned concurrency only on latency-sensitive functions
  • Timeouts, async patterns and batching reviewed
  • Concurrency limits checked