Pick the trigger
| Today | Serverless target |
|---|---|
| Cron job calling OCI APIs | Function invoked on a schedule |
| Script triggered by a file landing | Function triggered by an Object Storage event (Events service) |
| Small internal REST API | Function behind API Gateway |
| Start/stop instances on a timetable | Resource Scheduler (no code) |
| Long-running jobs (hours) | Container Instances or OKE jobs instead — Functions have a maximum timeout |
1. Create an application
oci fn application create --compartment-id $C --display-name ops-functions \
--subnet-ids '["<private-subnet-ocid>"]'
fn create context oci-fra --provider oracle
fn use context oci-fra
fn update context oracle.compartment-id $C
fn update context registry fra.ocir.io/<ns>/ops
2. Write the function
fn init --runtime python purge-old-exports
# func.py
import io, json, datetime, oci
from fdk import response
def handler(ctx, data: io.BytesIO = None):
signer = oci.auth.signers.get_resource_principals_signer()
os_client = oci.object_storage.ObjectStorageClient(config={}, signer=signer)
ns = os_client.get_namespace().data
cutoff = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=30)
deleted = 0
objs = oci.pagination.list_call_get_all_results(os_client.list_objects, ns, "exports", fields="timeCreated").data.objects
for o in objs:
if o.time_created < cutoff:
os_client.delete_object(ns, "exports", o.name)
deleted += 1
return response.Response(ctx, response_data=json.dumps({"deleted": deleted}), headers={"Content-Type": "application/json"})
fn deploy --app ops-functions
fn invoke ops-functions purge-old-exports
3. Resource principal permissions
ALL {resource.type = 'fnfunc', resource.compartment.id = '<comp-ocid>'} -- dynamic group 'fn-ops'
Allow dynamic-group 'Default'/'fn-ops' to manage objects in compartment data where target.bucket.name = 'exports'
No API keys inside the function.
4. Schedule it
Create a schedule that invokes the function (OCI Resource Scheduler supports function invocation on a cron-like schedule; check the regions and actions available to you). Alternatives: an OCI DevOps or external scheduler calling the function's invoke endpoint, or Events for event-driven jobs.
5. Expose an API
oci api-gateway gateway create --compartment-id $C --endpoint-type PRIVATE --subnet-id <subnet-ocid> --display-name gw-internal
Deployment spec route:
{ "routes": [ { "path": "/inventory", "methods": ["GET"],
"backend": { "type": "ORACLE_FUNCTIONS_BACKEND", "functionId": "<function-ocid>" } } ],
"requestPolicies": { "authentication": { "type": "JWT_AUTHENTICATION", "tokenHeader": "Authorization" } } }
Add authentication (JWT from your IdP or a custom authorizer function) and rate limiting.
6. Observe
Enable function invoke logs in OCI Logging, and alarm on the FunctionExecutionErrors-type metrics in the oci_faas namespace. Check metric names in your region's Monitoring metric explorer.
Note
Cold starts add latency to the first call after idle time. Use provisioned concurrency for latency-sensitive APIs.
Checklist
- Jobs inventoried; long-running ones routed elsewhere
- Functions use resource principals with narrow policies
- Schedules/events wired; API Gateway with auth
- Logs and alarms on errors
- Old VM retired