Skip to content

Agency AWS cloud management: operating client accounts without hiring a cloud team

How agencies manage client AWS accounts without a dedicated cloud team: one account per client, cross-account access instead of shared passwords, a repeatable baseline, and an honest answer for after-hours.

Most agencies end up operating client AWS accounts by accident: a site launch here, a migration there, and two years later fifteen production workloads depend on an agency whose actual business is design and development. Managing that portfolio without hiring a cloud team is possible, but only with structure — one AWS account per client, cross-account roles instead of shared passwords, a repeatable operations baseline stamped onto every account, and an honest answer to the after-hours question. Without those four, the agency is not managing infrastructure; it is accumulating liability at the pace of its own sales success.

What you are deciding

Three decisions define the model, and most agencies have made all three implicitly, badly.

The account structure. The wrong pattern is everything in one AWS account, client workloads separated by tag and hope — one compromised credential or one bad script reaches every client at once, and billing is archaeology. The right pattern is one account per client (per environment, ideally) under AWS Organizations: blast-radius isolation, per-client billing for free, and clean handover if the relationship ends. That last property matters more than agencies expect — the client owning their own account, with the agency as an operator inside it, is both the ethical position and the one that survives contract disputes.

The access model. Shared root credentials in a password vault is the pattern that eventually produces the industry’s ugliest incident reports. The replacement is IAM Identity Center: agency staff get named identities, permission sets define what each role can touch, access is revoked in one place when someone leaves, and every action lands in CloudTrail under a real name.

The service you are actually selling. “We host it” hides an enormous range: does it include monitoring with response, patching, backups with restore tests, incident response at 2 a.m., cost reviews? Each undefined item is being sold implicitly and delivered never. The decision is which of those you staff, which you contract to an operations partner behind the scenes, and which you explicitly decline in writing.

What to check first

  • How many client workloads share a single AWS account today, and how many staff know a root password.
  • Whether the agency could produce a per-client infrastructure cost figure without a spreadsheet afternoon.
  • What happens to a client’s production site on a Saturday night — concretely, whose phone, and do they know it.
  • Whether any client account has CloudTrail, backups, and alarms — or whether the baseline is whatever the launch-day engineer remembered.
  • Who legally owns each account: the client or the agency. Both answers work; not knowing does not.

How to verify

From the management account of an existing Organization:

# What accounts exist, and is there one per client?
aws organizations list-accounts \
  --query 'Accounts[].[Name,Id,Status]' --output table

# Who is this credential, and what account is it in?
aws sts get-caller-identity

Per client account, check the baseline actually exists:

# Is anything recording who did what?
aws cloudtrail describe-trails \
  --query 'trailList[].[Name,IsMultiRegionTrail,HomeRegion]'

# Do backups exist for the workloads that matter?
aws backup list-backup-jobs --by-state COMPLETED --max-results 5

# Root account hygiene: MFA on root, no root access keys
aws iam get-account-summary \
  --query 'SummaryMap.[AccountMFAEnabled,AccountAccessKeysPresent]'

In the console, IAM Identity Center > Users shows whether access is named individuals or one shared login pretending to be a team.

The approach

  1. Move to one account per client under Organizations. New clients get a fresh account from day one; existing co-tenants migrate at the next natural window (replatform, redesign, renewal). Control Tower’s Account Factory makes new-account creation a stamped, governed process instead of a checklist in someone’s head.
  2. Replace shared credentials with Identity Center. Named users, permission sets (read-only for PMs, operations for engineers, billing for finance), MFA enforced, root credentials sealed with MFA and used never.
  3. Stamp a baseline onto every account. CloudTrail, guardrails via service control policies — the starting set is in the Organizations SCP baseline — plus AWS Backup plans, a dozen symptom alarms, and a budget alert per account. Define it as code once; apply it every time.
  4. Make billing per-client by construction. Separate accounts do this automatically; consolidated billing still gives volume discounts at the Organization level. Resell at cost, cost-plus, or bundled — but decide, and put it in the contract.
  5. Write the service tiers. Tier one: hosting and backups, business-hours response. Tier two: plus monitoring with defined response times. Tier three: full operations with after-hours coverage. Price the pager honestly — it is the expensive part, which is exactly why it should not be given away implicitly.
  6. Decide build-versus-partner for the after-hours layer. An agency with two engineers cannot staff a real 24/7 rotation; pretending otherwise lasts until the first vacation-week outage. A white-label operations partner behind the agency covers the nights; the agency keeps the client relationship.
  7. Keep one runbook per client. Stack summary, access path, deploy procedure, escalation contacts, gotchas. The test: an engineer who has never touched the client can act within fifteen minutes.

When this is the wrong move

If infrastructure is three small brochure sites, this machinery is overhead — quality managed hosting per site is cheaper and safer than a half-built AWS practice. If a client’s workload has real compliance obligations (health data, payment processing at scale), the honest move is a specialized operations partner in that account, not agency best-effort. And if hosting margin is the only reason the agency holds these accounts, run the numbers including the unpaid incident hours; hosting revenue that costs weekends is not margin.

Common mistakes

  • One AWS account for all clients, discovered to be unsplittable years later when the biggest client asks for their keys.
  • Shared root logins, so departures require rotating every client’s credentials — which therefore never happens.
  • Selling “managed hosting” with response expectations that exist only in the client’s imagination, surfacing during the first real outage.
  • No exit story: account ownership, domain registrars, and DNS tangled in agency personal accounts, turning every offboarding into a hostage negotiation.

Keeping it under control

  • A quarterly portfolio review: every client account against the baseline checklist, deviations ticketed.
  • Budget alerts on every account, because a client’s surprise bill becomes the agency’s awkward phone call.
  • Access recertification twice a year: who has which permission set, and does the departed-staff list intersect it.
  • The runbooks tested by rotation — a different engineer executes a routine task from the runbook each quarter.
  • Contract language reviewed annually against what operations actually delivers.

The pattern that fails is fifteen accounts each managed from memory by whoever built them. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.