Cloud service names are easier to understand after the application’s needs are explicit. Our tiny notes API has stateless HTTP handlers, relational notes and occasional export objects. Those are different responsibilities even if a prototype stores everything beside one executable.
This course follows HTTP client policies and container packaging. You produce a complete reasoned infrastructure plan and run local checks. Required exercises use no account and provision nothing. A downloadable optional AWS networking lab is a separate hands-on choice; it does not deploy the whole application.
The process runs code and owns temporary memory. Relational storage preserves constrained records across restarts. Object storage holds export blobs independently of the process filesystem. A managed service changes the division of operational work, but does not remove your responsibility for access, schema, data recovery or application correctness.
Our mapping rubric offers managed compute versus a virtual machine and managed versus self-managed relational storage. It is a teaching choice under stated inputs, not a universal recommendation. Explain the reason for each placement instead of selecting a familiar product name first.
workloads=[("api","stateless HTTP"),("notes","relational records"),("exports","object blobs")]
for name,need in workloads:
print(name, "needs", need)
print("process-local files are not a recovery plan")Durable storage must outlive the process that uses it. An ephemeral container filesystem is not a database recovery plan. Equally, a managed database is not automatically private, backed up under your requirements or compatible with every SQLite behavior.
The build task returns stable category values and reasons in the original workload order. Reject state/access mismatches and duplicate names so later topology references remain unambiguous. The project README maps the abstract categories to illustrative AWS services without requiring them for the local lab.
from dataclasses import dataclass
import ipaddress
import re
class PlanError(ValueError):
pass
def bounded_text(value, label):
if not isinstance(value,str) or not value.strip() or len(value)>200:
raise PlanError(label)
return value
def integer(value, low, high):
if type(value) is not int or not low<=value<=high:
raise PlanError("integer outside plan bounds")
return value
@dataclass(frozen=True)
class Workload:
name: str
state: str
access: str
managed: bool
@dataclass(frozen=True)
class Placement:
name: str
category: str
reason: str
def map_workloads(workloads):
"""Choose a service category under this small explicit architecture rubric."""
if not isinstance(workloads,(list,tuple)) or not 1<=len(workloads)<=10:
raise PlanError("bounded workloads required")
result=[]
names=set()
for item in workloads:
if not isinstance(item,Workload):raise PlanError("typed workload required")
bounded_text(item.name,"name")
if item.name in names:raise PlanError("duplicate workload")
names.add(item.name)
if item.state not in ("stateless","relational","objects") or item.access not in ("http","sql","blob") or type(item.managed) is not bool:
raise PlanError("unsupported workload")
pair=(item.state,item.access)
if pair==("stateless","http"):
category="managed_compute" if item.managed else "virtual_machine"
reason="Run request handlers; durable data lives elsewhere."
elif pair==("relational","sql"):
category="managed_database" if item.managed else "self_managed_database"
reason="Keep constrained relational state with an explicit backup/restore owner."
elif pair==("objects","blob"):
category="object_storage"
reason="Store export objects separately from process-local files."
else:
raise PlanError("state/access contract mismatch")
result.append(Placement(item.name,category,reason))
return tuple(result)
for p in map_workloads([Workload("api","stateless","http",True),Workload("notes","relational","sql",True)]):
print(p.name,p.category)Implement the mapping rubric and explain why each kind of state lives where it does. Next place replicas and test whether a tier survives a zone or region failure.