CapEx and OpEx in Cloud Spending
Buying capacity is capital expenditure; renting it is operating expenditure. The shift changes who approves spending, how fast you can act, and which mistakes become expensive.
- Concept
- Why it matters to an engineer
- Architecture of a cloud bill
- Important terminology
- Worked example
- Commands
- Command options worth knowing
- Hands on lab
- Expected output
- Common mistakes
- Troubleshooting a rising bill
- Security considerations
- Best practices
- Interview questions
- Mini assignment
- Conclusion
Concept
Capital expenditure (CapEx) is money spent to acquire an asset you will use for years - servers, storage arrays, network switches. It is paid once, and its cost is spread across its useful life in the accounts.
Operating expenditure (OpEx) is money spent running the business day to day - rent, salaries, and cloud bills. It is charged in the period it is incurred.
Cloud converts most infrastructure spending from CapEx to OpEx. That is a finance sentence with heavy engineering consequences.
Why it matters to an engineer
- Approval changes. A large purchase needs a committee. A small monthly increase often needs a manager. This is why cloud teams move faster - and why costs drift upward unnoticed.
- Mistakes change shape. Buying the wrong server is one painful, visible mistake. Leaving the wrong server running is a small invisible charge that repeats every hour for a year.
- Optimisation becomes continuous. With owned hardware you optimise once at purchase. With OpEx, every week you do not switch something off costs money.
Architecture of a cloud bill
Total monthly cost
|
+-- Compute hours x instance size (largest for most teams)
+-- Storage GB stored per month + operations
+-- Data transfer GB leaving the provider, and between zones
+-- Managed services per request, per hour, or per provisioned unit
+-- Support plan and fixed platform feesCompute is usually the biggest line and the easiest to reduce. Data transfer is usually the least understood and the most surprising.
Important terminology
| Term | Meaning |
|---|---|
| CapEx | Spending that acquires a long lived asset. |
| OpEx | Spending consumed in the current period. |
| Depreciation | Spreading an asset cost across its useful life, commonly three to five years for servers. |
| Amortisation | The same idea applied to intangible assets such as licences. |
| Unit economics | Cost per meaningful unit - per user, per order, per thousand requests. The number worth tracking. |
| Commitment discount | A lower rate in exchange for promising a level of usage for one or three years. Partly returns you to CapEx thinking. |
| Showback | Reporting cost back to the team that caused it, without formally charging them. |
Worked example
An application needs four servers for three years. Compare the two shapes with round numbers.
| Item | Buy (CapEx) | Rent (OpEx) |
|---|---|---|
| Up front | 4 servers at 250,000 = 1,000,000 | 0 |
| Running, per year | Power, cooling, space, support: 90,000 | 4 instances at 6,500 per month = 312,000 |
| Three year total | 1,000,000 + 270,000 = 1,270,000 | 936,000 |
| If load doubles in year 2 | Buy 4 more: +1,000,000, plus lead time | +26,000 per month from the day you decide |
| If the project is cancelled in month 8 | Hardware already paid for | Stop paying in month 9 |
The currency is deliberately unnamed and the numbers are illustrative. The shape of the comparison is the lesson: CapEx is cheaper when you are certain, OpEx is cheaper when you are not.
Commands
Cost work starts with knowing what exists. These are read only AWS CLI examples using placeholders; the same pattern exists on every provider.
# Confirm which identity and account you are operating as
aws sts get-caller-identity
# List running instances with their type and name tag
aws ec2 describe-instances --region YOUR_REGION --filters "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].[InstanceId,InstanceType,Tags[?Key==`Name`]|[0].Value]" --output table
# Find volumes that are not attached to anything and are still billing
aws ec2 describe-volumes --region YOUR_REGION --filters "Name=status,Values=available" --query "Volumes[].[VolumeId,Size,CreateTime]" --output table
# Find addresses reserved but not associated, which also bill
aws ec2 describe-addresses --region YOUR_REGION --query "Addresses[?AssociationId==null].[PublicIp,AllocationId]" --output tableCommand options worth knowing
| Option | Effect |
|---|---|
--query | Filters and reshapes the response before it is printed, using JMESPath. |
--output table | Prints a readable grid. Use json when feeding another tool. |
--filters | Filters server side, so less data is returned and the call is faster. |
--region | Overrides the configured region for one command. Costs hide in regions you forgot about. |
Hands on lab
- Estimate, before running anything, what a single small always on server costs for a month in your chosen region.
- Now calculate the same server running only 09:00 to 19:00 on weekdays. That is about 220 hours instead of 730.
- Express the saving as a percentage. It should be close to seventy per cent.
- List three resource types that keep billing when nothing is using them. Detached disks, reserved addresses and idle load balancers are three good answers.
Expected output
Always on: 730 hours x rate
Business hours: 220 hours x rate
Saving: (730 - 220) / 730 = 69.9 per cent
Still billing while idle:
unattached disk volumes
reserved public addresses not associated with anything
load balancers with no healthy targets
snapshots kept forever with no retention ruleCommon mistakes
- Treating OpEx as free because there is no purchase order. Three small instances created weekly become a large annual number quietly.
- Committing to a discount too early. A one or three year commitment on a workload you have not measured recreates the CapEx problem with none of the asset.
- Optimising only compute. Storage kept forever and data transfer between zones often outgrow the servers.
- No tags. Without an owner tag, nobody knows whose resource it is, so nobody deletes it.
Troubleshooting a rising bill
| Step | Question | Action |
|---|---|---|
| 1 | What grew? | Compare this month to last by service, not by total |
| 2 | Where? | Break the growth down by region and by tag |
| 3 | Who owns it? | Read the owner tag; if there is none, that is the first finding |
| 4 | Is it doing work? | Check utilisation metrics before resizing or deleting |
| 5 | Will it recur? | Add a budget alert and a retention or shutdown rule |
Security considerations
- Cost data reveals architecture. Treat billing exports as sensitive internal information.
- Permission to create expensive resources is a security control. Restrict who can launch large instances or open data transfer paths.
- An unexplained cost spike can be an early sign of compromise, such as unauthorised compute for mining. Investigate spikes, do not just pay them.
Best practices
- Set a budget alert on day one, before the first resource exists.
- Tag everything with owner, environment and purpose, and enforce it.
- Track cost per meaningful unit, not just the total, so growth in usage is separated from waste.
- Schedule non production environments off outside working hours.
- Measure for at least a month before buying any commitment discount.
Interview questions
- Define CapEx and OpEx and give a cloud example of each.
- Why does the CapEx to OpEx shift make teams move faster, and what new risk does it create?
- Name four resources that continue to bill while completely idle.
- When would you advise against a three year commitment discount?
Mini assignment
Build a small spreadsheet comparing buying four servers against renting four instances for three years. Include power, cooling and staff time on the buy side, and data transfer on the rent side. Add a row showing what happens if demand doubles in year two, and write two sentences on which option you would choose and why.
Conclusion
CapEx buys certainty, OpEx buys flexibility. Cloud sells flexibility by the hour, which is excellent value only if someone is watching the meter.