Compartments are not folders: designing an OCI tenancy that stays manageable

Oracle Cloud puts everything in one tenancy and separates it with compartments. That is a different model from AWS accounts or Azure subscriptions, and copying either one produces a mess.

Teams arriving at Oracle Cloud from AWS look for the account boundary and find a compartment, decide it is the same thing, and build a tenancy with forty compartments mirroring their org chart. Six months later nobody can say which compartment a resource should go in, and the IAM policies are a wall of text.

A compartment is not an account. It is a logical container that policies are written against, and understanding that difference is most of the design.

What a compartment actually gives you

  • A policy target. IAM policies in OCI are sentences: allow group Developers to manage instance-family in compartment dev. The compartment is the noun that makes the sentence scope.
  • A quota boundary. You can set service limits per compartment, which is how you stop a team consuming the tenancy's GPU quota.
  • A cost dimension. Cost analysis groups by compartment, so the compartment is your primary cost attribution unit alongside tags.
  • A deletion unit. Deleting a compartment deletes what it contains, which is useful and dangerous in the usual proportions.

What it does not give you is a hard security boundary in the way a separate AWS account does. Everything lives in one tenancy, and a policy written at the tenancy level applies everywhere. The tenancy is the blast radius; compartments are how you organise within it.

The structure we deploy

Shallow and by function, not by team:

root (nothing lives here directly)
├── security          (vaults, logging, Cloud Guard config)
├── network           (VCNs, DRGs, load balancers, gateways)
├── shared            (registry, CI, bastion)
├── prod
│   ├── workload-a
│   └── workload-b
├── nonprod
│   ├── workload-a
│   └── workload-b
└── sandbox           (per-engineer, with quotas and a cleanup job)

Six levels of nesting are supported; two or three is what you should use. Policies inherit downward, so allow group NetworkAdmins to manage virtual-network-family in compartment network covers everything inside it without enumeration.

Keep the root compartment empty. Resources in root are the ones that cannot be moved cleanly later and that every tenancy-level policy touches.

Policies: few, inherited, and written against groups

Three rules keep OCI IAM readable:

Write policies at the highest compartment where they should apply. A policy per workload compartment repeated twenty times is twenty things to change.

Use dynamic groups for instance and function principals. A dynamic group matches resources by rule — all instances in a compartment, all functions with a tag — and lets you write allow dynamic-group app-instances to read objects in compartment data. This is how a workload authenticates without any credential at all, and it is the OCI equivalent of an instance profile. Anything still using an API signing key in a config file should be migrated to it.

Use conditions to narrow. OCI policy supports where clauses on request attributes, tags and target resource. allow group Ops to manage instance-family in compartment prod where request.permission != 'INSTANCE_DELETE' is the kind of thing that makes an on-call group safe to hand out.

Tags, which do more work here than elsewhere

OCI has free-form tags and defined tags — namespaced, typed and governable. Use defined tags: a namespace with Environment, Owner and CostCentre, with default values applied at compartment level so every resource created inside inherits them automatically.

That last feature — tag defaults per compartment — is genuinely better than the equivalents on other clouds, and it means the untagged-resource problem that opens the AWS bill piece can simply be prevented here.

Then use tag-based policies: allow group Developers to manage instances in compartment prod where target.resource.tag.Ops.Environment = 'test'.

Regions and availability domains

Subscribe only to the regions you operate in, and note that the home region is where IAM lives and cannot be changed. Some regions have one availability domain rather than three, which changes your high-availability design substantially — check this before you plan, because fault domains within a single AD are not the same protection as separate ADs.

Terraform and OCI Resource Manager

The oci provider is good and complete. One state per compartment per layer, stored in Object Storage or in OCI Resource Manager, which is Oracle's managed Terraform service and is genuinely convenient for teams that do not want to run their own pipeline. Authenticate CI with instance principals or resource principals rather than API keys, for the same reason keys are the wrong answer everywhere.

We lay this out at the start of an OCI engagement, and it is the structure the rest of the cloud work depends on.

What to do this week

List your compartments and, for each, write one sentence saying what policy it exists to scope. The ones where the sentence is about a team rather than a function are the ones to reconsider, because teams change and functions do not.

ConsultorIA

Want this done on your cloud?

A ten-day read-only assessment is free, and Skyline lets you see your estate on a map before you write to us.

Related articles

Modules people reuse instead of copying

The two failures are a module that wraps one resource and adds nothing, and a module that does everything and nobody dares change. A minimal interface, safe defaults and honest versioning are what separate them.