Most cloud automation starts life as a script on a schedule. Something runs every five minutes, asks a service whether anything changed, and acts if it did. The pattern works, but it scales badly: the polling interval is always too slow or too aggressive, the script needs somewhere to run around the clock, and the lag between a change and the response taxes every workflow built this way. The alternative is to stop asking and start listening, and on Oracle Cloud Infrastructure the service that makes that possible is OCI Events.
This article is the deep dive on Events within our broader series on application development and serverless on OCI. We will cover what the service is, how rules match and filter events, the three actions a rule can take, the anatomy of a real payload, which services emit events, the automation patterns we build most often, the delivery guarantees you must design around, and the limits that catch teams expecting Events to do more than it does.
What the Events service actually is
OCI Events is a fully managed event routing service built into the platform control plane. When a resource in your tenancy changes state, the owning service emits a structured event describing what happened. An object upload, an instance launch, a backup finishing, an autoscaling policy firing, a user added to a group: each produces an event automatically, with nothing configured on the resource itself. The events exist whether or not anyone is listening. Your job is to decide which ones matter and wire them to something.
The format is not proprietary. Events conform to the CloudEvents specification, the CNCF standard for describing event data in a common way, serialised as JSON. The envelope fields are therefore predictable, every event carries a type, a source, a time, an identifier, and a data section, and tooling that understands CloudEvents works against OCI events without translation, which keeps consumers portable and parsing code boring, which is exactly what parsing code should be.
There is no charge for the Events service itself. You pay for whatever the rule invokes, a function execution, a notification delivery, a message written to a stream, but matching and routing are free. Rules that never fire cost nothing, and rules that fire cost only what their actions cost.
How rules work
A rule is the unit of configuration in Events, and it has three parts: a scope, a condition, and one or more actions. The scope is the compartment the rule lives in. A rule matches events from its own compartment and all child compartments beneath it, so a rule high in the tree observes a wide slice of the tenancy while a leaf compartment rule sees only its own corner. Choosing where a rule lives is a real design decision, not an afterthought.
The condition is a JSON pattern that incoming events are matched against. The primary key is the event type, a namespaced string such as com.oraclecloud.objectstorage.createobject or com.oraclecloud.computeapi.launchinstance.end. A condition can name one event type, a list of them, or omit the type to match everything in scope, which is occasionally useful for audit style capture and almost always a mistake for automation. Beyond the type, conditions match on attributes inside the event: the compartment identifier, the availability domain, resource specific fields such as the bucket name, and freeform tags on the resource that changed. Matching is exact and case insensitive, and multiple conditions combine as a logical AND, so a rule can express something as precise as: object created, in this bucket, on resources tagged with this cost centre.
Filter tags are the cleanest way to make automation opt in. Rather than matching every instance termination in a compartment, tag the instances that need special handling and write the rule to match the tag. The rule logic stays stable while teams control participation by tagging, a far better operating model than editing rule conditions every time the fleet changes.
The three actions
When a rule matches, it triggers its actions, and there are exactly three kinds: invoke a function, publish to a Notifications topic, or write to a stream. Each suits a different consumer, and a single rule can carry multiple actions, so one event can fan out to several destinations at once.
| Action type | What happens | Best suited for |
|---|---|---|
| Functions | The event payload is delivered as the input to a function invocation | Automated remediation, processing pipelines, any logic that should run in response to the event |
| Notifications | The event is published to a topic and fanned out to all subscriptions | Alerting humans by email or Slack, triggering PagerDuty, fanning one event to many endpoints |
| Streaming | The event is appended as a message to a stream partition | Buffered consumption, replayable history, feeding external systems that read at their own pace |
The Functions action is the workhorse for automation. The event arrives as the invocation payload, your code parses it, acts, and exits, and nothing runs between events. We covered the execution model, identity, and failure handling in our OCI Functions guide, and everything there applies doubly to event triggered functions, because nobody is watching a synchronous response when they fail.
The Notifications action is how events reach people and third party systems. A topic receives the event and delivers it to every subscription: email addresses, Slack channels, PagerDuty services, custom HTTPS endpoints, even functions again. The fan out is the point; one autoscale event can simultaneously email the platform team, post to a channel, and hit a webhook. The mechanics of topics, subscriptions, and delivery retries are covered in our article on OCI Notifications.
The Streaming action writes the event to a stream, which changes the consumption model entirely. Functions and Notifications push; Streaming lets consumers pull. Events written to a stream sit in ordered, replayable storage for the retention period, so a consumer that was down for an hour catches up from where it left off, and multiple independent consumers can read the same history. When the consumer cannot guarantee availability at the moment the event fires, the stream is the right buffer.
Anatomy of an event payload
Every event is a JSON document with a consistent envelope. The fields you will use constantly are eventType, the namespaced type string the rule matched on; source, the emitting service; eventTime, when the state change occurred; eventID, a unique identifier for this specific emission; and data, the section describing the resource that changed. Inside data you will reliably find the compartment identifier and name, the resource identifier and name, and, where applicable, the availability domain. Crucially, data also carries the freeform and defined tags on the resource, which is what makes tag based filtering and tag aware consumers possible.
Service specific detail lives in an additionalDetails block within data. For an Object Storage event that means the namespace, the bucket name, and the archival state; for a compute event it means shape and image information. Treat additionalDetails as the variable part of the contract: parse the envelope generically, then branch on eventType before reaching into the details. The most useful habit when building consumers is to log the full payload of the first real event you receive and write your parser against that, not against what you assumed. The documentation gives reference schemas per event type, but the live event is the ground truth.
Who emits events, and who does not
Coverage is broad but not universal, and assuming a service emits events is a classic planning error. The heavy emitters are the core infrastructure services: Object Storage on object create, update, and delete; Compute on launch, termination, and lifecycle transitions, with begin and end variants for long operations; Autoscaling when a policy triggers a scale action; the Database services on provisioning, backup, and patching milestones; Identity on changes to users, groups, and policies. Networking, Block Volume, Load Balancer, Functions, and Container Engine all emit useful lifecycle events too.
What Events does not carry is anything your own applications generate. There is no API for publishing a custom event; the service transports control plane state changes and nothing else. If your application needs to emit its own business events, an order placed, a document approved, the right tools are Streaming for high volume ordered feeds or OCI Queue for decoupled point to point messaging with individual acknowledgement. Teams arriving from platforms with a custom event bus often expect to publish through the same pipe as infrastructure events, and on OCI those are deliberately separate concerns.
The automation patterns we build most often
Object upload triggers processing
The canonical pattern. A file lands in a bucket, the createobject event matches a rule scoped to that bucket, and a function picks it up: generating thumbnails, parsing a CSV into a database, virus scanning an upload, kicking off a document pipeline. Nothing polls the bucket, nothing runs between uploads, and the cost is exactly proportional to the work. Almost every tenancy we touch ends up with at least one of these.
Autoscale events keep humans informed
Autoscaling that nobody notices is a silent cost and capacity story. A rule matching the autoscaling action event, wired to a Notifications topic, means the platform team sees every scale out and scale in as it happens, with the instance pool and trigger details in the payload. It costs effectively nothing and removes a whole category of end of month surprise.
Security response automation
Identity events are an underused goldmine. A rule that matches policy or group membership changes in sensitive compartments, invoking a function that captures the change, posts to the security channel, and optionally reverts anything outside an approved change window, converts a quarterly audit finding into a real time control. The same pattern applies to public bucket creation and security list modifications: match the event, evaluate against policy, remediate or escalate.
Tagging compliance enforcement
Cost allocation lives and dies on tags, and tags decay. A rule matching resource creation events can invoke a function that checks the new resource for mandatory tags and either applies defaults, notifies the owner, or quarantines the resource. Enforcement at creation time, triggered by the creation event itself, beats any retrospective cleanup job ever written.
Delivery semantics: design for duplicates
Events delivers at least once, not exactly once. That phrase carries a lot of weight. The service guarantees your action will be triggered for a matching event, retrying delivery if the target fails or is unavailable, but it does not guarantee the action fires only once. Under retry conditions, and occasionally under normal operation, a consumer will receive the same event twice. Retries continue for a substantial window, hours rather than seconds, so a function that was briefly broken can receive a backlog of redelivered events when it recovers.
The design consequence is that every consumer must be idempotent. The eventID field exists precisely for this: key side effects on it, record processed identifiers, and skip work already done. A thumbnail generator that runs twice wastes pennies; a function that provisions a resource or sends a customer email twice does real damage. Equally important is the failure path. A consumer that throws on a malformed payload will throw on every retry of it, so distinguish poison input from transient failure early, and push events you cannot process to a queue or stream with enough context to diagnose and replay them. Silent loss of failed events is the defect we find most often in event driven estates, and it is invisible until the day it matters.
Events versus polling, and Events versus Service Connector Hub
Against polling the comparison is short. Polling trades latency against API load and needs a place to run; Events delivers within seconds of the state change, generates no read traffic, and runs nowhere until it fires. Polling still earns its keep only for services that do not emit the event you need, and for reconciliation sweeps that verify the event driven path missed nothing, which mature estates run weekly rather than every five minutes.
Service Connector Hub is the comparison that actually confuses teams, because both move data between OCI services and both can target Functions. The distinction is what they carry. Events is a matching engine for discrete state changes: a rule evaluates each event and triggers actions per event. Service Connector Hub is a bulk data mover: it continuously transfers logs, metrics, and stream contents from a source to a target, optionally transforming batches through a function. If the question is "did this specific thing happen, and what should react", that is Events. If the question is "move everything this service produces over to that service", that is a service connector. Plenty of architectures use both.
Limits and gotchas
The constraints are few but firm. The largest is the one already noted: no custom application events, full stop, so plan application messaging on Streaming or Queue from the start. Second is matching scope: a rule placed too low in the compartment tree silently misses events from elsewhere, and one placed at the root can match far more than intended. Third, conditions match on equality against the attributes the event actually carries; there is no regular expression matching and no numeric comparison, so anything fancier belongs inside the consumer. Fourth, actions per rule are capped, ten at the time of writing, and a disabled rule matches nothing, which sounds obvious until someone disables a rule for a test and forgets it. Finally, testing: the fastest way to validate a rule is to perform the real state change in a test compartment and watch the action fire, and the console's event matching validator lets you paste a sample payload against your condition first. Treat rules as code, keep them in Terraform, and review condition changes the way you review IAM changes, because a wrong condition fails silently in both directions.
A framework for designing event driven automation
When we design an event driven workflow in an engagement, the sequence below is the one we follow. It front loads the questions that hurt when discovered late.
- Inventory the state changes that matter. List the operational moments you care about and confirm each against the documented event types for the emitting service.
- Verify the payload carries what the consumer needs. Trigger the real event once and capture it; if a field is missing, the consumer must fetch it by resource identifier, which changes its permissions.
- Choose the rule scope and placement. Pick the compartment so the rule sees everything it should and nothing it should not, and prefer filter tags for opt in behaviour.
- Pick the action per consumer. Functions for logic, Notifications for humans and webhooks, Streaming for buffered or replayable consumption, fanning out when one event has several audiences.
- Design the consumer for at least once delivery. Key side effects on the eventID, make replays harmless, and separate poison input from transient failure.
- Wire the dead letter path before go live. Route unprocessable events to a queue or stream with alerting on depth, so failures are visible and replayable rather than silent.
- Codify and monitor the whole chain. Keep rules in Terraform, alarm on action failures and consumer errors, and run a periodic reconciliation sweep to confirm nothing was missed.
Bringing it together
OCI Events is a small service with outsized leverage. It costs nothing to match, speaks a standard format, covers the state changes that matter most, and connects cleanly to the three destinations automation actually needs: code, people, and buffered pipelines. The discipline it demands in return is modest but real: idempotent consumers, deliberate rule scoping, a dead letter path, and respect for the boundary between infrastructure events and application messaging. Where Events fits in the larger picture, alongside Streaming, Queue, and Notifications as the messaging backbone of a tenancy, is the subject of our companion piece on event driven architecture on OCI. And if you are building out the landing zone, the IAM model, and the automation layer that rules and consumers depend on, that is precisely the work our OCI implementation service delivers.
Free white paper
Go deeper on this topic with The OCI Landing Zone and Architecture Guide, a reference architecture for security, networking, and governance on OCI. An independent analyst style report with comparison tables and recommendations, free with a work email. Prefer a monthly summary instead? The OCI Brief delivers one practical OCI briefing a month.
Part of a series
This guide is part of OCI Platform & Architecture — our complete pillar guide on the topic.
Moving Oracle workloads to OCI, or already running on OCI and not sure the architecture or the spend is right? Most teams bring in a specialist before they commit to a region, a shape, or a Universal Credits number. OCISpecialists.com plans the landing zone, runs the migration, and manages the estate after go live, on a fixed project fee, a managed monthly retainer, or a cost optimization fee paid only on verified savings.