You Rented the Server, Not the Outcome: Cloud Execution Models and Who Is Responsible

A team migrates a database from a server they ran to a managed service. The provider now handles patching, backups, and failover, and the team is genuinely better off. Four months later an audit finds the database reachable from the internet with a weak password, because the thing that moved was the operating system and the thing that did not was the configuration. Nobody misread a document. Nobody read one.

Choosing a cloud execution model is choosing which work you keep. The models are well documented and the boundary between them is not intuitive, so it is worth reading the boundary directly. Descriptions below follow the AWS and Microsoft documentation as of September 2026.

Three models, described by what you still operate

Microsoft’s definitions are usefully blunt about this. IaaS: “you manage virtual machines, operating systems, and applications.” PaaS: “you deploy applications without managing VMs or operating systems.” SaaS: “you use ready-made applications.” Serverless functions sit at the far end of PaaS — you deploy code and the platform decides when and where it runs.

Read as a progression, each step removes an operational duty and adds a constraint. IaaS gives you any operating system and hands you its patching. Serverless removes the machine entirely and takes away long-lived local state. The question is never which is most modern; it is which constraint your workload can accept.

The boundary, line by line

The shared responsibility model is the industry’s name for this division. AWS states the principle — “security and compliance is a shared responsibility between AWS and the customer” — and the part worth memorizing: “customer responsibility will be determined by the AWS Cloud services that a customer selects.” The boundary is a property of the service, not of the provider.

Microsoft publishes the division as a matrix, and reading it row by row is more informative than any diagram.

ResponsibilityOn-premisesIaaSPaaSSaaS
Customer dataYouYouYouYou
Configurations and settingsYouYouYouYou
Identities and usersYouYouYouYou
ApplicationsYouYouSharedShared
Network controlsYouYouSharedProvider
Operating systemYouYouProviderProvider
Physical hosts, network, datacenterYouProviderProviderProvider

The first three rows are the ones that matter for planning, because they do not move. The documentation states it directly: whatever the deployment type, you always retain data (including “data classification, data protection, encryption decisions”), endpoints, accounts, and access management (“role-based access control (RBAC), multifactor authentication, and conditional access policies”).

Which explains the opening story precisely. The managed database moved the operating-system row. It did not move the configuration row or the identity row, and those are where the incident happened.

What “managed” actually transfers

AWS’s description of the difference between running a virtual machine and using a storage or database service is the clearest statement of the shift. Deploy EC2 instances and you are responsible for “management of the guest operating system (including updates and security patches), any application software or utilities installed by the customer on the instances, and the configuration of the AWS-provided firewall.”

Use a service such as S3 or DynamoDB and “AWS operates the infrastructure layer, the operating system, and platforms, and customers access the endpoints to store and retrieve data” — with your attention moving to “managing their data (including encryption options), classifying their assets, and using IAM tools to apply appropriate permissions.”

Patch management is the example that shows the split inside a single duty: “AWS is responsible for patching and fixing flaws within the infrastructure, but customers are responsible for patching their guest OS and applications.” A duty can be shared rather than transferred, and assuming otherwise is the most common way an unpatched system survives a migration.

Two practical habits follow. Write down, per service you adopt, which rows moved and which did not — one line each, in the design document rather than in someone’s memory. And treat the rows that never move as the permanent operational surface: access review, key rotation, and configuration drift remain yours at every level of managed service, and they are what audits find.

State is what decides the model

Ask what the workload keeps between requests and the choice narrows quickly, because each model treats local state differently.

Serverless makes the strongest demand, and the documentation is specific about why. After an invocation “the execution environment is frozen” and retained for possible reuse, which has consequences worth designing around: objects declared outside the handler “remain initialized,” and the /tmp directory — “between 512 MB and 10,240 MB” — persists as “a transient cache that can be used for multiple invocations.”

That reuse is an optimization to exploit and never a guarantee to depend on. The same page states the limit plainly: “Lambda terminates execution environments every few hours to allow for runtime updates and maintenance—even for functions that are invoked continuously. You should not assume that the execution environment will persist indefinitely.” There is a sharper trap in the failure path — after an invocation error the platform resets the environment, and the reset “does not clear the /tmp directory content before the next init phase,” so leftover files can reach the next invocation.

The design rule that follows: cache in the environment, keep truth outside it. A connection or a compiled model in the initialization block is a legitimate speed-up; a counter, an accumulated file, or a queue of pending work is a bug waiting for the next recycle. That is what a stateless service means in practice, and it is also what makes horizontal scaling possible — any instance can serve any request because none of them holds anything the others need.

Containers sit in the middle: a writable filesystem exists and disappears with the container, which is enough for scratch space and not for anything a restart must survive. Virtual machines let you keep local state, and that is exactly why they are the harder thing to scale and to replace.

Elasticity is a property of your design, not of the platform

Providers sell the ability to add and remove capacity. Whether your workload benefits depends on three things the platform cannot supply.

  • Requests that any instance can serve. Session state pinned to one machine makes scaling out a routing problem instead of a capacity fix.
  • Retries that are safe. Scaling events cause interruptions, so work has to be repeatable without double effect — plain idempotency, and the requirement people discover after a scale-in event has charged two customers.
  • Start-up fast enough to matter. Capacity that arrives after the spike is expensive decoration. For functions this is the cold start question, and the documented figures set expectations: cold starts “typically occur in under 1% of invocations” with a duration “from under 100 ms to over 1 second,” reducible by pre-initializing environments through provisioned concurrency.

Worth noting that elasticity and isolation are different goals, easily confused when buying. Adding capacity handles load; keeping one workload from disturbing another is workload isolation, and a single elastic pool shared by everything provides the first and not the second.

Choosing, and what each choice costs later

ChooseWhenWhat you accept
Virtual machinesLicensed or legacy software, kernel-level requirements, a lift-and-shift with a deadline, or software that keeps local state you cannot redesign yetYou own the operating system and its patching, and you pay for capacity whether or not it is used
ContainersMany services with similar runtime needs; you want the same artifact in every environment and control over how it runsA scheduling layer you have to place somewhere — either an orchestrator you operate, or a managed container service that runs one for you and constrains what you can configure
Serverless functionsEvent-driven work, spiky or low-volume traffic, glue between services, anything where idle cost should be zeroStatelessness, execution limits, cold starts, and a deployment shape specific to the provider
Managed data and platform servicesAlmost always, for databases, queues, and storage — unless a requirement genuinely rules them outConfiguration, data, and identity stay yours, and so does the provider’s version schedule

The container row hides a second decision that is easy to miss. Packaging in a container does not commit you to operating a cluster: the providers all offer services that accept a container image and run it without exposing a control plane, and the cost then is not operations but reduced control — the networking model, the scaling behaviour, and the sidecar and node-level tricks available to you are whatever the service allows. Running your own orchestrator buys back that control and takes on upgrades, capacity, and the accompanying expertise. Which is why “we chose containers” is not yet an answer; the question is whose scheduler runs them.

Two cost questions belong in the decision rather than after it. First, compare the whole cost: staff time, on-call burden, and the skills required are part of total cost of ownership, and a managed service that is more expensive per hour is frequently cheaper per year. Second, name what leaving would take. The further up the stack you go the more the provider’s shape is baked into your code, so portability deserves a stated position — and the honest form of that position is an estimated exit cost rather than a preference for open tools.

One structural note that recurs through cloud architecture: most managed services separate the part that decides from the part that does the work — the control plane and the data plane. It is worth knowing which is which for services you depend on, because they fail differently: a control-plane outage can leave running workloads healthy while preventing any change, and a team that has not distinguished them will read one as the other during an incident.

Where to start

For one workload you are placing or moving, four questions settle most of it, in this order.

  • What does it keep between requests, and can that move to a managed store? The answer eliminates models rather than ranking them.
  • What is its traffic shape? Steady load favours reserved capacity; spiky or occasional load is where per-invocation pricing and scale-to-zero earn their keep.
  • Which responsibility rows move, and which stay? Write the answer down. This is the step that prevents the audit finding.
  • What would leaving cost? Not as an objection — as a number, so the decision is made with it rather than against it.

Even for a local development setup the same instinct applies at small scale: a virtual environment isolates dependencies for exactly the reason a container does in production, which is why the habit transfers upward more easily than teams expect.

References: AWS, Shared Responsibility Model; Microsoft Learn, Shared responsibility in the cloud (documentation updated 2026-08-24); AWS Lambda Developer Guide, Understanding the Lambda execution environment lifecycle.


Discover more from Insightful Data Lab

Subscribe to get the latest posts sent to your email.

Similar Posts

Questions, corrections, or additional insights?

This site uses Akismet to reduce spam. Learn how your comment data is processed.