Pair your devices with a code and playback position follows you: pause on this device, hit resume on the other. Position is saved to the site every minute and on pause.
Open this panel on your other device and enter the same code.
You will need: AWS CLI v2, jq, a default VPC, and permission to call Cost Explorer, Budgets,
Compute Optimizer, S3 and EC2 (describe + VPC endpoints). Cost Explorer must already be enabled on the
account.
Write your answers down. Questions are numbered Q1…Q20.
⚠️ Safety: nothing here launches compute. The two things that bill at all are Cost Explorer API requests ("$0.01" per paginated request) and a few bytes of S3. Run the teardown today anyway.
export LAB=saa4-$(date +%Y%m%d)-$RANDOM
export REGION=$(aws configure get region)
export ACCT=$(aws sts get-caller-identity --query Account --output text)
export VPC=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true \
--query 'Vpcs[0].VpcId' --output text)
echo "LAB=$LAB REGION=$REGION ACCT=$ACCT VPC=$VPC"
Lesson 1 says Cost Explorer shows "up to the last 13 months". Look at yours.
START=$(date -v-3m +%Y-%m-01 2>/dev/null || date -d '3 months ago' +%Y-%m-01)
END=$(date +%Y-%m-01)
aws ce get-cost-and-usage --time-period Start=$START,End=$END \
--granularity MONTHLY --metrics UnblendedCost \
--group-by Type=DIMENSION,Key=SERVICE \
--query 'ResultsByTime[].Groups[?Metrics.UnblendedCost.Amount>`1`].[Keys[0],Metrics.UnblendedCost.Amount]' \
--output table
Q1. List your top three services by cost last month. Then state what that one command cost you, and quote the sentence from lesson 1 that tells you.
Now look for data transfer — the usage types lesson 5 depends on:
aws ce get-cost-and-usage --time-period Start=$START,End=$END \
--granularity MONTHLY --metrics UsageQuantity UnblendedCost \
--group-by Type=DIMENSION,Key=USAGE_TYPE \
--query 'ResultsByTime[-1].Groups[?contains(Keys[0],`DataTransfer`) || contains(Keys[0],`NatGateway`)].[Keys[0],Metrics.UnblendedCost.Amount]' \
--output table
Q2. Which data-transfer or NAT usage types appear? For each, say which row of lesson 5's direction
table it corresponds to. If you see a DataTransfer-Regional-Bytes line, what kind of traffic is it,
and why does lesson 1 say you'll see two line items per transfer?
Q3. Cost allocation tags:
aws ce list-cost-allocation-tags --status Active --query 'CostAllocationTags[].[TagKey,Type]' --output table
aws ce list-cost-allocation-tags --status Inactive --max-results 20 \
--query 'CostAllocationTags[].[TagKey,Type]' --output table
How many tags are active, and how many are sitting inactive? If you are not in the management account, what happened when you ran this, and which sentence from lesson 1 explains it?
Q4. Create a forecasted-cost budget that emails you at 80%:
cat > /tmp/$LAB-budget.json <<EOF
{"BudgetName":"$LAB","BudgetLimit":{"Amount":"10","Unit":"USD"},
"TimeUnit":"MONTHLY","BudgetType":"COST"}
EOF
cat > /tmp/$LAB-notif.json <<EOF
[{"Notification":{"NotificationType":"FORECASTED","ComparisonOperator":"GREATER_THAN",
"Threshold":80,"ThresholdType":"PERCENTAGE"},
"Subscribers":[{"SubscriptionType":"EMAIL","Address":"you@example.com"}]}]
EOF
# edit the email address first
aws budgets create-budget --account-id $ACCT \
--budget file:///tmp/$LAB-budget.json \
--notifications-with-subscribers file:///tmp/$LAB-notif.json
aws budgets describe-budget --account-id $ACCT --budget-name $LAB \
--query 'Budget.{Limit:BudgetLimit,Actual:CalculatedSpend.ActualSpend,Forecast:CalculatedSpend.ForecastedSpend}'
Record the actual and forecasted spend. Why is FORECASTED the right notification type for "warn us
before"? And why, per lesson 1, might the forecast here look stale?
Q5. This budget only emails. Name the feature that would stop spend, the three kinds of action it can take, and the one thing a management account cannot do to a member account with it.
BUCKET=$LAB-bucket
aws s3api create-bucket --bucket $BUCKET \
$( [ "$REGION" != "us-east-1" ] && echo --create-bucket-configuration LocationConstraint=$REGION )
head -c 4096 /dev/urandom > /tmp/$LAB-4k.bin
aws s3api put-object --bucket $BUCKET --key tiny-ia.bin --body /tmp/$LAB-4k.bin --storage-class STANDARD_IA
aws s3api put-object --bucket $BUCKET --key tiny-std.bin --body /tmp/$LAB-4k.bin
aws s3api head-object --bucket $BUCKET --key tiny-ia.bin --query '{Size:ContentLength,Class:StorageClass}'
Q6. The object is 4,096 bytes. How many bytes will you be billed for in Standard-IA, and for how many days, even if you delete it in five minutes? Quote both minimums. Compute the multiplier against its real size.
Q7. Now apply a lifecycle rule that tries to move everything to Glacier Instant Retrieval after 30 days and then to Deep Archive after 60:
cat > /tmp/$LAB-lc.json <<'EOF'
{"Rules":[{"ID":"waterfall","Status":"Enabled","Filter":{},
"Transitions":[{"Days":30,"StorageClass":"GLACIER_IR"},
{"Days":60,"StorageClass":"DEEP_ARCHIVE"}]}]}
EOF
aws s3api put-bucket-lifecycle-configuration --bucket $BUCKET \
--lifecycle-configuration file:///tmp/$LAB-lc.json 2>&1 | tail -3
Did it succeed? Lesson 2 quotes AWS's rule about chaining transitions faster than a minimum duration. Using Glacier IR's 90-day minimum, state the earliest day the Deep Archive transition is allowed, fix the JSON, and re-apply it. Record what you changed.
Q8. Read the configuration back:
aws s3api get-bucket-lifecycle-configuration --bucket $BUCKET
With the September 2024 default, will your 4 KB objects transition at all? Quote the constraint, and name the filter you'd add to override it — then explain why you wouldn't.
Q9. Requester Pays:
aws s3api put-bucket-request-payment --bucket $BUCKET \
--request-payment-configuration Payer=Requester
aws s3api get-object --bucket $BUCKET --key tiny-std.bin /tmp/$LAB-out1 2>&1 | tail -1
aws s3api get-object --bucket $BUCKET --key tiny-std.bin --request-payer requester /tmp/$LAB-out2 \
--query ContentLength
What happened on the first call and the second? (As the bucket owner your result may differ from a cross-account requester — note what you saw and whether it matches lesson 2.) Who pays for storage now, and can this bucket serve anonymous users?
Q10. Spot price history for one type across AZs:
aws ec2 describe-spot-price-history --instance-types m5.large \
--product-descriptions "Linux/UNIX" --start-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--query 'SpotPriceHistory[].[AvailabilityZone,SpotPrice]' --output table
Do the AZs differ? Lesson 3 quotes how the Spot price is set — does "adjusted gradually" match what you see? What is the Spot interruption notice period, and when is there none?
Q11. Hibernation support:
aws ec2 describe-instance-types --instance-types m5.large t3.micro c7g.large \
--query 'InstanceTypes[].[InstanceType,HibernationSupported]' --output table
Record the result. Lesson 3 flags hibernation prerequisites as unverified — you've now verified one attribute for three types. State the use case AWS names for hibernation and what you're still billed for while hibernated.
Q12. Compute Optimizer:
aws compute-optimizer get-enrollment-status
Are you opted in? If yes, what's the default metric lookback and the paid extension? If no, which lesson 1 sentence explains why there are no recommendations?
Lesson 5's headline claim: "There is no additional charge for using gateway endpoints." Build one and see the route it adds.
RTB=$(aws ec2 describe-route-tables --filters Name=vpc-id,Values=$VPC Name=association.main,Values=true \
--query 'RouteTables[0].RouteTableId' --output text)
aws ec2 describe-route-tables --route-table-ids $RTB --query 'RouteTables[0].Routes[].[DestinationCidrBlock,DestinationPrefixListId,GatewayId]' --output table
VPCE=$(aws ec2 create-vpc-endpoint --vpc-id $VPC --vpc-endpoint-type Gateway \
--service-name com.amazonaws.$REGION.s3 --route-table-ids $RTB \
--query 'VpcEndpoint.VpcEndpointId' --output text)
sleep 10
aws ec2 describe-route-tables --route-table-ids $RTB --query 'RouteTables[0].Routes[].[DestinationCidrBlock,DestinationPrefixListId,GatewayId]' --output table
Q13. Compare the two route tables. What was added — destination and target? Why does this route win
over 0.0.0.0/0 for S3 traffic in this Region? Quote the longest-prefix-match sentence.
Q14. Why does this save money only when a NAT gateway was in the path? (The default VPC's subnets are public, so here it saves nothing — say why.) What does a NAT gateway charge that this endpoint doesn't?
Q15. Name the three limits of a gateway endpoint from lesson 5: which services, which Region, and what about a peered VPC.
Q16. For each, name the purchase and justify it in one sentence with a quote:
| # | Workload |
|---|---|
| a | 40 m5 instances run 24/7; next year half move to Fargate |
| b | nightly rendering, restartable, 6 hours, any instance family |
| c | SQL Server with existing per-core licences |
| d | steady workload needing guaranteed capacity in one AZ |
Q17. A DynamoDB table does 400 eventually consistent reads/s of 10 KB items and 50 writes/s of 2.5 KB items. Compute RCU and WCU for provisioned mode. Then say which capacity mode you'd pick if traffic were unknown, and quote AWS.
Q18. Dev VPC (3 AZs, light traffic) and prod VPC (3 AZs, heavy traffic, must survive AZ loss). Design the NAT for each and justify with the lesson 5 quotes.
Q19. 2 VPCs with heavy traffic vs 40 VPCs plus on-premises. Choose the interconnect for each. How many peering links would a 40-VPC full mesh need? Show the formula.
Q20. An on-premises link needs 3 Gbps to AWS for six weeks while Direct Connect is ordered. Design it, and state the two configuration requirements AWS names.
aws ec2 delete-vpc-endpoints --vpc-endpoint-ids $VPCE
aws s3api delete-bucket-lifecycle --bucket $BUCKET
aws s3api put-bucket-request-payment --bucket $BUCKET --request-payment-configuration Payer=BucketOwner
aws s3 rm s3://$BUCKET --recursive
aws s3api delete-bucket --bucket $BUCKET
aws budgets delete-budget --account-id $ACCT --budget-name $LAB
rm -f /tmp/$LAB-*
Verify it — don't assume it:
aws ec2 describe-vpc-endpoints --vpc-endpoint-ids $VPCE --query 'VpcEndpoints[].State' 2>&1 | tail -1
aws s3api head-bucket --bucket $BUCKET 2>&1 | tail -1
aws budgets describe-budgets --account-id $ACCT --query "Budgets[?BudgetName=='$LAB'].BudgetName"
The endpoint should be deleted or not found, the bucket should return a 404/NotFound, and the budget
list should be empty. Remember the Standard-IA object is billed for 30 days regardless — that's Q6's
lesson, paid for.