Oracle Cloud's invisible 47 GB floor
Oracle Cloud's Always-Free tier is genuinely generous: 4 ARM cores, 24 GB RAM, and "200 GB of block storage." I used it to build a 3-node HA k3s cluster plus a small load-balancer node. Then my budget alert started twitching.
The surprise
I had 5 instances. I checked my block usage:
47 GB server-1 47 GB edge
47 GB server-2 47 GB oracle-monitor
47 GB server-3
──────────────────────────────────────────
235 GB total / 200 GB free → 35 GB OVER
Every instance — even the tiny 1 GB AMD micros — has a 47 GB boot volume, and boot volumes count against the same 200 GB pool. The OS uses ~5 GB; the other ~42 is just… there. Five instances and you're over budget, paying a euro or so a month for storage you're not using.
So the obvious question: can I shrink those boot volumes?
Dead end #1 — shrink the boot volume
No. OCI volumes can only grow, never shrink. And the docs are explicit:
For Linux images, the custom boot volume size must be larger than the image's default boot volume size or 50 GB, whichever is higher.
So if you customize, the floor is 50 GB — bigger, not smaller. The only way to sit below 50 is to take the image's own default (47 GB) and not touch it. You literally cannot request less.
Dead end #2 — the famous qemu-img trick
The community classic: attach a blank block volume, write a tiny cloud image onto
it with qemu-img convert, boot from that. Clever — but OCI block volumes have
a 50 GB minimum (that's why every guide says "add a 50 GB volume"). So this
hands you a 50 GB volume, which is bigger than the 47 GB default. It lets you run
a different/leaner OS, but it reclaims zero quota.
Dead end #3 — import a minimal image (the one that should work)
Here's where it got interesting. That same rule has an asymmetry: a boot volume
can be under 50 GB if the image's own default is under 50. Real minimal cloud
images are tiny — the Debian genericcloud arm64 image is a 3 GiB virtual disk
(326 MB download). So: import that, and surely you get a ~3 GB boot volume?
I tested it instead of guessing. Imported the 3 GiB Debian image via Object Storage and asked the API what size OCI assigned it:
imported_image_size_mb = "47694"
47694 MB ≈ 46.6 GB — the exact same number as Oracle's own Ubuntu image. OCI pads every imported image up to its floor. The 3 GB image became a 47 GB image on import. Dead end confirmed, by experiment.
The conclusion
There is a universal ~47 GB floor on OCI instances. No knob, no trick, no slim image gets under it:
| Approach | Result |
|---|---|
| Custom boot volume size | floored at 50 GB |
qemu-img → block volume | block volumes floored at 50 GB |
| Import a 3 GB minimal image | clamped to 47 GB on import |
What to actually do
- Plan your instance count around it. Each instance ≈ 47 GB. The 200 GB free pool realistically fits ~4 instances. Want more (I wanted 5, for HA)? Budget ~€0.025/GB-month for the overage — about €1/month. It's a floor, not waste.
- Or run fewer, bigger boxes. This is why most "ultimate free-tier" guides build one instance with all 4 cores and 200 GB — one boot volume, lots of headroom. You trade HA for €0.
- For Kubernetes PVs, use
local-path, which carves from the ~42 GB of free space already inside each boot volume. Don't add OCI block-volume PVs — those pile billable storage on top of a pool you've already maxed.
The free tier is still a fantastic deal. Just know that "200 GB" really means "~4 instances," and that the 47 GB floor is real, universal, and — now — empirically proven.