Why write a profile before you pick a tool
In Level 1 you saw the whole AWS ops toolbox on one page. Now comes the step most teams skip: writing down what your estate needs before you open any service page. Think of it like a structural survey before you renovate. You don't choose between steel and timber beams until you know the span and the load.
An operations profile is a short document, usually one page of YAML or a table, with nine sections:
- Estate size and environments
- Telemetry volume and retention
- SLOs and alerting
- IaC and change control
- Patching
- Cost allocation
- Guardrails (keep this short; the security course covered it)
- Team skills
- Cost model
Every lesson after this one ends with "choose it when / avoid it when". Those verdicts mean little unless you can hold them up against this profile. Three rules apply: use numbers, make every requirement testable, and mark each one must-have or nice-to-have.
Step 1: Measure, don't guess
Start from the real estate. If you have one, these read-only commands give you the starting numbers:
# How many accounts? (run from the Organizations management account)
aws organizations list-accounts --query 'length(Accounts)'
# How many running EC2 instances in this account/Region?
aws ec2 describe-instances \
--filters Name=instance-state-name,Values=running \
--query 'length(Reservations[].Instances[])'
# Which log groups have NO retention set? (they keep data forever by default)
aws logs describe-log-groups \
--query 'logGroups[?retentionInDays==`null`].logGroupName'
# How many alarms exist today?
aws cloudwatch describe-alarms --query 'length(MetricAlarms)'
# Daily log volume for one busy log group (uncompressed bytes per day)
aws cloudwatch get-metric-statistics --namespace AWS/Logs \
--metric-name IncomingBytes \
--dimensions Name=LogGroupName,Value=/app/checkout \
--start-time 2026-10-01T00:00:00Z --end-time 2026-10-29T00:00:00Z \
--period 86400 --statistics Sum
Gotcha: A new CloudWatch log group keeps its data indefinitely until you set a retention policy. That third command often turns up years of logs nobody asked to keep. The allowed retention values run from 1 day up to 3,653 days (10 years).
Repeat for each account and Region you care about. If you don't have an estate yet, use the sample below and swap in your own figures later.
Step 2: Fill in the profile
Here is a worked profile for a fictional retailer, "ShopCo":
# ops-profile.yaml — ShopCo, drafted 2026-10-30
estate:
accounts: 12 # prod, staging, dev x 3 business units + shared + log archive + audit
environments: [prod, staging, dev]
regions: [eu-west-2, us-east-1]
ec2_instances: 180 # 70 prod
containers_tasks: 400
lambda_functions: 250
telemetry:
logs_gb_per_day: 20 # measured from IncomingBytes, rounded up
retention_days: { prod: 90, staging: 30, dev: 7 } # MUST
archive_years: 1 # audit needs a year of prod logs - MUST
custom_metrics: 1500
alarms: 300
slos_alerting:
- service: checkout
slo: "99.9% of requests succeed over 30 days" # MUST
alert: "page on-call within 5 minutes of a fast error-budget burn" # MUST
- service: search
slo: "95% of requests < 300 ms over 30 days" # NICE
iac_change:
tool_today: mixed # some console clicks, some Terraform
requirement: "100% of prod changes via reviewed code" # MUST
drift_check: weekly # NICE
patching:
requirement: "critical OS patches in prod within 7 days" # MUST
window: "Sun 02:00-04:00 UTC"
cost_allocation:
required_tags: [CostCentre, Environment, Owner] # MUST
showback: monthly per business unit # MUST
guardrails: "no public S3; approved Regions only" # MUST (detail: security course)
team:
size: 6
skills: { python: strong, terraform: medium, cloudformation: low, grafana: none }
cost_model:
ops_tooling_budget_usd_month: 3000 # MUST
preference: "pay-as-you-go over licences" # NICE
Step 3: Turn vague needs into measurable requirements
A requirement you can't test is only a wish. Rewrite each one until someone could prove it passed or failed:
| Vague | Measurable |
|---|---|
| "Checkout must be reliable" | "99.9% of checkout requests succeed over a rolling 30 days" |
| "Alert us quickly" | "Page on-call within 5 minutes of a fast burn of the 99.9% SLO's error budget" |
| "Keep logs for a while" | "Prod logs searchable for 90 days, archived for 1 year" |
| "Stay patched" | "Critical OS patches applied in prod within 7 days of release" |
| "Know who spends what" | "Every resource carries CostCentre, Environment and Owner tags; monthly report per unit" |
Turn the SLO into time you can picture. 99.9% over 30 days allows 0.1% failure. 30 days × 24 h × 60 min = 43,200 minutes, and 0.1% of that is about 43 minutes of full outage a month. That figure is your error budget. A 5-minute paging requirement makes sense against a 43-minute budget. A 30-minute one would spend most of the month's budget before anyone was paged.
Step 4: Put rough prices on the volume numbers
You'll study pricing per service later. For now, a back-of-envelope check stops you writing a profile you can't afford. Using CloudWatch list prices for US East (N. Virginia) as of October 2026 (dated examples; always recheck):
Log ingestion: 20 GB/day x 30 days = 600 GB x $0.50/GB = $300/month
Custom metrics: 1,500 x $0.30 (first-tier rate) ≈ $450/month
Standard alarms: 300 x $0.10 = $30/month
rough total ≈ $780 + storage
That fits ShopCo's $3,000 budget. If logs were 200 GB/day, ingestion alone would be about $3,000 a month, and the profile would need to change.
Trade-off: Long retention is cheap to write down and costly to keep. Set prod, staging and dev separately. Dev rarely needs more than a week.
Gotcha for cost allocation: User-defined tags don't appear in billing reports until you activate them. After you first apply a tag, it can take up to 24 hours to show up for activation and up to another 24 hours to become active. Add "activate cost allocation tags" to day one of any launch plan.
Step 5: Mark must-have vs nice-to-have
You saw the # MUST / # NICE labels above. They become the weights in the selection scorecard near the end of the course. Keep the test strict: a must-have is one where failing it rules the option out (a legal duty, an SLO in a contract, a budget ceiling). Everything else is nice-to-have. If more than about half your lines say MUST, you haven't made real choices yet.
Best practice: Put a date and an owner on the profile and keep it in version control next to your IaC. Estates grow, and a profile from a year ago will steer you wrong.
Key takeaways
- The operations profile has nine sections. Write it before you compare any service.
- Measure real numbers with read-only CLI calls: accounts, instances, GB of logs per day, retention, metrics and alarms.
- New CloudWatch log groups never expire by default. Set retention for each environment on purpose.
- Rewrite vague needs until they can be tested. A 99.9% SLO over 30 days leaves about 43 minutes of error budget.
- Do quick, dated cost arithmetic so the profile stays within budget.
- Tag every requirement MUST or NICE. Those labels become your scorecard weights.
- Activate cost allocation tags early. It can take up to 48 hours in total.