Files
nexus/sreweekly/articles/448/02-mutable-vs-immutable-infrastructure-models-in-the-cloud-era.html
2026-09-12 17:23:01 +08:00

3110 lines
164 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Explore mutable infrastructure and immutable structures: learn which offers flexibility for updates, consistency, reliability, and fits different cloud needs.">
<meta name="keywords" content="Disaster recovery, Infrastructure, cloud, systems, terraform">
<meta property="og:description" content="Explore mutable infrastructure and immutable structures: learn which offers flexibility for updates, consistency, reliability, and fits different cloud needs.">
<meta property="og:site_name" content="dzone.com">
<meta property="og:title" content="Mutable vs. Immutable: Infrastructure Models in the Cloud Era">
<meta property="og:url" content="https://dzone.com/articles/infrastructure-models-in-the-cloud-era">
<meta property="og:image" content="https://dz2cdn1.dzone.com/storage/article-thumb/17974679-thumb.jpg">
<meta property="og:type" content="article">
<meta name="twitter:site" content="@DZoneInc">
<meta name="twitter:image" content="https://dz2cdn1.dzone.com/storage/article-thumb/17974679-thumb.jpg">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:description" content="Explore mutable infrastructure and immutable structures: learn which offers flexibility for updates, consistency, reliability, and fits different cloud needs.">
<meta name="twitter:title" content="Mutable vs. Immutable: Infrastructure Models in the Cloud Era">
<meta name="referrer" content="origin-when-cross-origin">
<meta name="google-site-verification" content="kndbhxcupfEqWmZclhCpB6vlgOs7QSmx2UHAGGnP2mA">
<meta name="df-verify" content="df0d76632b4543">
<link rel="icon" type="image/x-icon" href="https://dz2cdn1.dzone.com/themes/dz20/images/favicon.png">
<link rel="image_src" href="https://dz2cdn1.dzone.com/storage/article-thumb/17974679-thumb.jpg">
<link rel="canonical" href="https://dzone.com/articles/infrastructure-models-in-the-cloud-era">
<title>Mutable vs. Immutable: Infrastructure Models in the Cloud Era</title>
<link rel="preload" href="https://dz2cdn1.dzone.com/themes/dz20/font/fontello.woff?11773374" as="font" type="font/woff" crossorigin="anonymous">
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/icons.css">
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/lib/static/bootstrap/bootstrap.min.css">
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/article/global.css">
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/header-updated/styles.css">
<style>
:root {
--xs-size: 2px;
--sm-size: 5px;
--md-size: 10px;
--lg-size: 15px;
--xl-size: 25px;
--sm-border-size: 8px;
--sm-font-size: 13px;
--sm-plus-font-size: 16px;
--md-font-size: 18px;
--lg-font-size: 22px;
--xl-font-size: 26px;
}
/* Display Quick-Access Classes */
.display-none { display: none; }
.display-block { display: block; }
.display-inline { display: inline; }
.display-inline-block { display: inline-block; }
/* Margin Quick-Access Classes */
.m-xs { margin: var(--xs-size); }
.m-sm { margin: var(--sm-size); }
.m-md { margin: var(--md-size); }
.m-lg { margin: var(--lg-size); }
.m-xl { margin: var(--xl-size); }
.mt-xs, .my-xs { margin-top: var(--xs-size); }
.mr-xs, .mx-xs { margin-right: var(--xs-size); }
.mb-xs, .my-xs { margin-bottom: var(--xs-size); }
.ml-xs, .mx-xs { margin-left: var(--xs-size); }
.mt-sm, .my-sm { margin-top: var(--sm-size); }
.mr-sm, .mx-sm { margin-right: var(--sm-size); }
.mb-sm, .my-sm { margin-bottom: var(--sm-size); }
.ml-sm, .mx-sm { margin-left: var(--sm-size); }
.mt-md, .my-md { margin-top: var(--md-size); }
.mr-md, .mx-md { margin-right: var(--md-size); }
.mb-md, .my-md { margin-bottom: var(--md-size); }
.ml-md, .mx-md { margin-left: var(--md-size); }
.mt-lg, .my-lg { margin-top: var(--lg-size); }
.mr-lg, .mx-lg { margin-right: var(--lg-size); }
.mb-lg, .my-lg { margin-bottom: var(--lg-size); }
.ml-lg, .mx-lg { margin-left: var(--lg-size); }
.mt-xl, .my-xl { margin-top: var(--xl-size); }
.mr-xl, .mx-xl { margin-right: var(--xl-size); }
.mb-xl, .my-xl { margin-bottom: var(--xl-size); }
.ml-xl, .mx-xl { margin-left: var(--xl-size); }
.ml-auto, .mx-auto { margin-left: auto; }
.mr-auto, .mx-auto { margin-right: auto; }
.mt-auto, .my-auto { margin-top: auto; }
.mb-auto, .my-auto { margin-bottom: auto; }
.my-none, .mt-none { margin-top: 0 !important; }
.mx-none, .mr-none { margin-right: 0 !important; }
.my-none, .mb-none { margin-bottom: 0 !important; }
.mx-none, .ml-none { margin-left: 0 !important; }
/* Padding Quick-Access Classes */
.p-xs { padding: var(--xs-size); }
.p-sm { padding: var(--sm-size); }
.p-md { padding: var(--md-size); }
.p-lg { padding: var(--lg-size); }
.p-xl { padding: var(--xl-size); }
.pt-xs, .py-xs { padding-top: var(--xs-size); }
.pr-xs, .px-xs { padding-right: var(--xs-size); }
.pb-xs, .py-xs { padding-bottom: var(--xs-size); }
.pl-xs, .px-xs { padding-left: var(--xs-size); }
.pt-sm, .py-sm { padding-top: var(--sm-size); }
.pr-sm, .px-sm { padding-right: var(--sm-size); }
.pb-sm, .py-sm { padding-bottom: var(--sm-size); }
.pl-sm, .px-sm { padding-left: var(--sm-size); }
.pt-md, .py-md { padding-top: var(--md-size); }
.pr-md, .px-md { padding-right: var(--md-size); }
.pb-md, .py-md { padding-bottom: var(--md-size); }
.pl-md, .px-md { padding-left: var(--md-size); }
.pt-lg, .py-lg { padding-top: var(--lg-size); }
.pr-lg, .px-lg { padding-right: var(--lg-size); }
.pb-lg, .py-lg { padding-bottom: var(--lg-size); }
.pl-lg, .px-lg { padding-left: var(--lg-size); }
.pt-xl, .py-xl { padding-top: var(--xl-size); }
.pr-xl, .px-xl { padding-right: var(--xl-size); }
.pb-xl, .py-xl { padding-bottom: var(--xl-size); }
.pl-xl, .px-xl { padding-left: var(--xl-size); }
.py-none, .pt-none { padding-top: 0 !important; }
.px-none, .pr-none { padding-right: 0 !important; }
.py-none, .pb-none { padding-bottom: 0 !important; }
.px-none, .pl-none { padding-left: 0 !important; }
/* Flex Quick-Access Classes */
.flex {
display: flex;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-column-reverse {
display: flex;
flex-direction: column-reverse;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-row-reverse {
display: flex;
flex-direction: row-reverse;
}
.flex-wrap {
flex-wrap: wrap;
}
.flex-grow {
flex-grow: 1;
}
.align-center { align-items: center; }
.align-end { align-items: flex-end; }
.content-center {
align-content: center;
}
.justify-center { justify-content: center; }
.justify-start { justify-content: flex-start; }
.justify-end { justify-content: flex-end; }
.justify-around { justify-content: space-around; }
.justify-between { justify-content: space-between; }
.justify-evenly { justify-content: space-evenly; }
.gap-sm { gap: var(--sm-size); }
.gap-md { gap: var(--md-size); }
.gap-lg { gap: var(--lg-size); }
.gap-xl { gap: var(--xl-size); }
/* Display Quick-Access Classes */
.inline-block { display: inline-block; }
/* Font Quick-Access Classes */
.font-xl { font-size: var(--xl-font-size); }
.font-lg { font-size: var(--lg-font-size); }
.font-md { font-size: var(--md-font-size); }
.font-sm-plus { font-size: var(--sm-plus-font-size); }
.font-sm { font-size: var(--sm-font-size); }
.font-strike { text-decoration: line-through; }
.font-underline { text-decoration: underline; }
.font-overline { text-decoration: overline; }
.font-italic { font-style: italic; }
.font-bold { font-weight: bold; }
.font-black { color: #000000; }
.font-white { color: #ffffff; }
.font-gray { color: var(--brand-gray-text); }
.font-danger { color: var(--header-dropdown-button-bg-danger); }
.font-center { text-align: center; }
.no-wrap { white-space: nowrap; }
/* Consistent headings between h and non-h tags */
.heading {
margin-top: 0;
margin-bottom: var(--md-size);
}
.heading.font-xl { line-height: var(--xl-font-size); }
.heading.font-lg { line-height: var(--lg-font-size); }
.heading.font-md { line-height: var(--md-font-size); }
.heading.font-sm-plus { line-height: var(--sm-plus-font-size); }
.heading.font-sm { line-height: var(--sm-font-size); }
/* Font Clamp Quick-Access Classes */
.line-clamp,
.line-clamp-2,
.line-clamp-3,
.line-clamp-4,
.line-clamp-5 {
display: -webkit-box;
-webkit-line-clamp: 4;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.line-clamp-2 { -webkit-line-clamp: 2 !important; }
.line-clamp-3 { -webkit-line-clamp: 3 !important; }
.line-clamp-4 { -webkit-line-clamp: 4 !important; }
.line-clamp-5 { -webkit-line-clamp: 5 !important; }
/* User-Select Quick-Access Classes */
.select-none { user-select: none; }
/* Position Quick-Access Classes */
.absolute { position: absolute; }
.relative { position: relative; }
.float-left { float: left; }
.float-right { float: right; }
.pos-top { top: 0; }
.pos-right { right: 0; }
.pos-bottom { bottom: 0; }
.pos-left { left: 0; }
.va-top { vertical-align: top; }
.va-middle { vertical-align: middle; }
.va-bottom { vertical-align: bottom; }
/* Transition Quick-Access Classes */
.trans-linear-quick {
transition: all 0.15s linear;
}
/* Background Quick-Access Classes */
.bg-gray { background: #cccccc; }
.bg-white { background-color: white; }
.bg-none { background: none; }
/* Border Quick-Access Classes */
.border-gray { border: 1px solid #cccccc; }
.tab-pane.border-gray { border: 1px solid #ddd; }
.no-border, .border-none { border: none !important; }
.bt-none { border-top: none !important; }
.br-none { border-right: none !important; }
.bb-none { border-bottom: none !important; }
.bl-none { border-left: none !important; }
/* Border Radius Quick-Access Classes */
.round-t-sm, .round-tl-sm { border-top-left-radius: var(--sm-border-size); }
.round-t-sm, .round-tr-sm { border-top-right-radius: var(--sm-border-size); }
.round-b-sm, .round-bl-sm { border-bottom-left-radius: var(--sm-border-size); }
.round-b-sm, .round-br-sm { border-bottom-right-radius: var(--sm-border-size); }
.round-sm { border-radius: var(--sm-border-size); }
.round-fully { border-radius: 50%; }
/* Misc Quick-Access Classes */
.haikei {
position: relative;
background-image: url('https://dz2cdn1.dzone.com/themes/dz20/images/polygon-scatter-haikei-shapes.svg');
background-repeat: no-repeat;
background-size: cover;
}
.haikei:before {
content: '';
position:absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--color-event-background);
z-index: -1;
}
.margin-auto-center {
display: block;
margin-left: auto;
margin-right: auto;
}
.flex-auto-center {
display: flex;
margin-left: auto;
margin-right: auto;
}
.mw-1100 { max-width: 1100px; }
.mw-1300 { max-width: 1300px; }
.full-width { width: 100%; }
.h-separator {
background-color: #cccccc;
height: 1px;
width: 100%;
margin: 5px auto;
}
.no-spacing {
margin: 0 !important;
padding: 0 !important;
}
.inherit-color { color: inherit; }
.inherit-decoration { text-decoration: inherit; }
/* Table Quick-Access Classes */
.table-border-gray tr:not(:last-child) {
border-bottom: 1px solid #cccccc;
}
table.full-width tr td:last-child {
width:100%;
}
/* Animation Quick-Access Classes */
@keyframes anim-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(359deg); }
}
.anim-spin {
display: inline-block;
animation: anim-spin 2s infinite linear;
}
.hov-pointer { cursor: pointer; }
.hov-brighten:hover { filter: brightness(1.2); }
.hov-darken:hover { filter: brightness(0.95); }
.hov-underline:hover { text-decoration: underline; }
/* Small tweaks related to components when using these styles */
.nav-tabs {
border-bottom: none;
}
.tab-content > .flex-column.active,
.tab-content > .flex-row.active {
display: flex;
}
/* Alpine components with x-cloak should not be visible by default until conditionals kick in */
[x-cloak] { display: none !important; }
</style>
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/alpine-components/modal.css">
<script defer src="https://dz2cdn1.dzone.com/themes/dz20/lib/alpinejs/3.13.2/cdn.min.js"></script>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('article', {
id: null,
engagement: {
open: false,
page: 1,
users: [],
additional: true,
loading: false,
initializing: false,
unauthorized: false,
enqueued: null,
dequeued: null,
reset() {
this.open = false;
this.page = 1;
this.users.splice(0);
this.additional = true;
this.loading = false;
this.initializing = false;
this.enqueued = null;
this.dequeued = null;
},
enqueue(user) {
this.dequeued = null;
this.enqueued = user;
},
dequeue(user) {
this.enqueued = null;
this.dequeued = user;
},
add(user) {
this.users.push(user);
this.enqueued = null;
},
remove(user) {
const index = this.users.findIndex(u => u.id === user.id);
if (index !== -1) {
this.users.splice(index, 1);
}
this.dequeued = null;
},
contains(user) {
return this.users.filter(u => u.id === user.id).length;
}
}
});
Alpine.effect(() => {
const store = Alpine.store('article');
if (!store.engagement.additional && store.engagement.enqueued) {
if (!store.engagement.contains(store.engagement.enqueued)) {
store.engagement.add(store.engagement.enqueued);
}
}
});
Alpine.effect(() => {
const store = Alpine.store('article');
if (store.engagement.page && store.engagement.dequeued) {
store.engagement.remove(store.engagement.dequeued);
}
})
});
</script></head>
<body x-data>
<div class="skybox skybox-closeBtn dz_skybox" data-gpt-slot="skybox" id="div-gpt-ad-1435246566686-99"></div>
<header id="ftl-header">
<div class="header-top">
<div class="header-container">
<div class="pull-left logo-container">
<div class="logo">
<a class="inner" href="/">
<picture>
<source srcset="https://dz2cdn1.dzone.com/themes/dz20/images/dz_logo_2021_cropped.webp" type="image/webp">
<source srcset="https://dz2cdn1.dzone.com/themes/dz20/images/dz_logo_2021_cropped.png" type="image/png">
<img src="https://dz2cdn1.dzone.com/themes/dz20/images/dz_logo_2021_cropped.png" width="181" height="56" alt="DZone">
</picture>
</a>
</div>
</div>
<div class="pull-right login-and-search">
<div id="authenticated-block" class="logged-in">
<div class="welcome-back">Thanks for visiting DZone today,</div>
<div id="user-header" class="user-info">
<button class="user-avatar">
<span id="header-username" class="username"></span>
<img id="header-avatar" src="" alt="user avatar">
</button>
<div id="user-dropdown" class="browse-user-menu">
<div class="user-content">
<a id="header-user-plug" href="#" class="user-description"></a>
<a id="header-user-edit" href="#" class="edit-profile">Edit Profile</a>
</div>
<ul class="user-actions">
<li id="first-user-action">
<a id="header-dropdown-manage-email" href="#">Manage Email Subscriptions</a>
</li>
<li>
<a href="/articles/how-to-submit-a-post-to-dzone?utm_source=DZone&utm_medium=user_dropdown&utm_campaign=how_to_post">
How to Post to DZone
</a>
</li>
<li>
<a href="/articles/dzones-article-submission-guidelines">
Article Submission Guidelines
</a>
</li>
</ul>
<div class="bottom">
<a href="/users/logout.html" class="sign-out">Sign Out</a>
<a id="dropdown-view-profile" href="#" class="view-profile">View Profile</a>
</div>
</div>
</div>
<div class="post-content">
<button id="post-button" class="post-content--button">
<span class="post-class">Post</span>
<i class="icon-plus"></i>
</button>
<div id="post-menu" class="posting-links">
<div class="posting-links-menu">
<ul>
<li>
<img src="https://dz2cdn1.dzone.com/themes/dz20/images/dz-postarticle.svg" width="15" height="18" style="width: 15px; height: 18px;">
<a href="/content/article/post.html">Post an Article</a>
</li>
<li>
<a id="drafts-link" href="#">Manage My Drafts</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div id="unauthenticated-block">
<div class="dz-intro">Over 2 million developers have joined DZone.</div>
<div class="mobile-invisible sign-in-join">
<a href="/users/login.html">Log In</a>
<span class="dz-intro-span">/</span>
<a href="/static/registration.html">Join</a>
</div>
<a class="join-icon" href="/users/login.html" aria-label="User">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide svg-user lucide-user-icon lucide-user">
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</a>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.data('searchDrawer', () => ({
open: false,
query: '',
minCharsMet: false,
toggleVisibility() {
this.open = !this.open;
if (this.open) {
this.$nextTick(() => {
this.$refs.query.focus();
});
}
},
updateSearchValue() {
if (!this.query || !this.query.length || this.query.length < 3) {
this.minCharsMet = false;
return;
}
this.minCharsMet = true;
localStorage.setItem('ls.searchValue', this.query);
},
searchSite() {
if (this.minCharsMet) {
window.location = '/search';
}
}
}));
});
</script>
<div class="headerSearch" x-data="searchDrawer()" x-cloak>
<button class="btn-search dropdown-toggle" x-on:click="toggleVisibility()" aria-label="Search">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide svg-search lucide-search-icon lucide-search">
<path d="m21 21-4.34-4.34"></path>
<circle cx="11" cy="11" r="8"></circle>
</svg>
</button>
<template x-teleport=".header-container">
<div id="search-drawer" x-show="open" x-on:click.outside="open = false" x-transition>
<div class="search-input">
<input type="text"
placeholder="Search"
autofocus="autofocus"
x-model="query"
x-ref="query"
x-on:input.change="updateSearchValue()"
x-on:keyup.enter="searchSite()"
>
<button x-on:click="searchSite()" x-bind:disabled="!minCharsMet">
<span>Search</span>
</button>
</div>
<div class="search-footer">
Please enter at least three characters to search
</div>
</div>
</template>
</div>
</div>
</div> </div>
<div class="header-bottom">
<div class="header-bottom-container">
<a class="resource-link" href="/refcardz">Refcards</a>
<a class="resource-link" href="/trendreports">Trend Reports</a>
<div class="resource-link link-menu">
<a href="/events">Events</a>
<a href="/events/video-library">Video Library</a>
</div>
</div>
</div>
<nav class="header-menu-bar">
<div class="header-menu resource-category">
<a href="/refcardz">Refcards</a>
</div>
<div class="header-menu-separator resource-category-separator"></div>
<div class="header-menu resource-category">
<a href="/trendreports">Trend Reports</a>
</div>
<div class="header-menu-separator resource-category-separator"></div>
<div class="header-menu resource-category no-bottom-radius" data-click-activation>
<p class="menu-label">Events</p>
<div class="header-menu-items">
<div class="header-menu-columns">
<a class="header-menu-item" href="/events">View Events</a>
<a class="header-menu-item" href="/events/video-library">Video Library</a>
</div>
</div>
</div>
<div class="header-menu zone-menu" data-click-activation>
<p class="menu-label">Zones <i class="icon-down-dir icon-closed"></i><i class="icon-right-dir icon-open"></i></p>
<div class="header-menu-items">
<div class="header-menu-columns">
<div class="header-menu-column-item">
<a class="header-menu-item" href="/culture-and-methodologies">Culture and Methodologies</a>
<a class="header-menu-item" href="/agile">Agile</a>
<a class="header-menu-item" href="/career-development">Career Development</a>
<a class="header-menu-item" href="/methodologies">Methodologies</a>
<a class="header-menu-item" href="/team-management">Team Management</a>
</div>
<div class="header-menu-column-item">
<a class="header-menu-item" href="/data-engineering">Data Engineering</a>
<a class="header-menu-item" href="/ai-ml">AI/ML</a>
<a class="header-menu-item" href="/big-data">Big Data</a>
<a class="header-menu-item" href="/data">Data</a>
<a class="header-menu-item" href="/databases">Databases</a>
<a class="header-menu-item" href="/iot">IoT</a>
</div>
<div class="header-menu-column-item">
<a class="header-menu-item" href="/software-design-and-architecture">Software Design and Architecture</a>
<a class="header-menu-item" href="/cloud-architecture">Cloud Architecture</a>
<a class="header-menu-item" href="/containers">Containers</a>
<a class="header-menu-item" href="/integration">Integration</a>
<a class="header-menu-item" href="/microservices">Microservices</a>
<a class="header-menu-item" href="/performance">Performance</a>
<a class="header-menu-item" href="/security">Security</a>
</div>
<div class="header-menu-column-item">
<a class="header-menu-item" href="/coding">Coding</a>
<a class="header-menu-item" href="/frameworks">Frameworks</a>
<a class="header-menu-item" href="/java">Java</a>
<a class="header-menu-item" href="/javascript">JavaScript</a>
<a class="header-menu-item" href="/languages">Languages</a>
<a class="header-menu-item" href="/tools">Tools</a>
</div>
<div class="header-menu-column-item">
<a class="header-menu-item" href="/testing-deployment-and-maintenance">Testing, Deployment, and Maintenance</a>
<a class="header-menu-item" href="/deployment">Deployment</a>
<a class="header-menu-item" href="/devops-and-cicd">DevOps and CI/CD</a>
<a class="header-menu-item" href="/maintenance">Maintenance</a>
<a class="header-menu-item" href="/monitoring-and-observability">Monitoring and Observability</a>
<a class="header-menu-item" href="/testing-tools-and-frameworks">Testing, Tools, and Frameworks</a>
</div>
<div class="header-menu-column-item sponsored">
<a class="header-menu-item" href="javascript:void(0)">Partner Zones</a>
<a class="header-menu-item" href="/hubs/build-ai-agents-that-are-ready-for-production/">Build AI Agents That Are Ready for Production</a>
</div>
</div>
</div>
</div>
<div class="header-menu parent-category" tabindex="1">
<a href="/culture-and-methodologies">Culture and Methodologies</a>
<div class="header-menu-items">
<a class="header-menu-item" href="/agile">Agile</a>
<a class="header-menu-item" href="/career-development">Career Development</a>
<a class="header-menu-item" href="/methodologies">Methodologies</a>
<a class="header-menu-item" href="/team-management">Team Management</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
<div class="header-menu parent-category" tabindex="2">
<a href="/data-engineering">Data Engineering</a>
<div class="header-menu-items">
<a class="header-menu-item" href="/ai-ml">AI/ML</a>
<a class="header-menu-item" href="/big-data">Big Data</a>
<a class="header-menu-item" href="/data">Data</a>
<a class="header-menu-item" href="/databases">Databases</a>
<a class="header-menu-item" href="/iot">IoT</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
<div class="header-menu parent-category" tabindex="3">
<a href="/software-design-and-architecture">Software Design and Architecture</a>
<div class="header-menu-items">
<a class="header-menu-item" href="/cloud-architecture">Cloud Architecture</a>
<a class="header-menu-item" href="/containers">Containers</a>
<a class="header-menu-item" href="/integration">Integration</a>
<a class="header-menu-item" href="/microservices">Microservices</a>
<a class="header-menu-item" href="/performance">Performance</a>
<a class="header-menu-item" href="/security">Security</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
<div class="header-menu parent-category" tabindex="4">
<a href="/coding">Coding</a>
<div class="header-menu-items">
<a class="header-menu-item" href="/frameworks">Frameworks</a>
<a class="header-menu-item" href="/java">Java</a>
<a class="header-menu-item" href="/javascript">JavaScript</a>
<a class="header-menu-item" href="/languages">Languages</a>
<a class="header-menu-item" href="/tools">Tools</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
<div class="header-menu parent-category" tabindex="5">
<a href="/testing-deployment-and-maintenance">Testing, Deployment, and Maintenance</a>
<div class="header-menu-items">
<a class="header-menu-item" href="/deployment">Deployment</a>
<a class="header-menu-item" href="/devops-and-cicd">DevOps and CI/CD</a>
<a class="header-menu-item" href="/maintenance">Maintenance</a>
<a class="header-menu-item" href="/monitoring-and-observability">Monitoring and Observability</a>
<a class="header-menu-item" href="/testing-tools-and-frameworks">Testing, Tools, and Frameworks</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
<div class="header-menu parent-category sponsored" tabindex="6">
<a href="javascript:void(0)">Partner Zones</a>
<div class="header-menu-items sponsored">
<a class="header-menu-item" href="/hubs/build-ai-agents-that-are-ready-for-production/">Build AI Agents That Are Ready for Production</a>
</div>
</div>
<div class="header-menu-separator parent-category-separator"></div>
</nav>
</header>
<script>
const csrf = {
parameter: 'TH_CSRF',
header: 'X-TH-CSRF',
token: '-7950453983214790953'
}; // set csrf for auth-status script
</script>
<script>
addEventListener('DOMContentLoaded', function() {
handleRedirects();
handleMenus();
handleMobileMenuHeights();
handleGotoLinks();
});
function isHidden(element) {
try {
return window.getComputedStyle(element).display === 'none';
} catch (_) {
return false;
}
}
function getLink(element) {
if (element.hasAttribute('data-goto')) {
return element.getAttribute('data-goto');
}
return element.href;
}
function isLeftClick(event) {
if (event.altKey || event.shiftKey) {
return false;
} else if ('buttons' in event || 'which' in event) {
return event.buttons === 1 || event.which === 1;
} else {
return (event.button === 1 || (event.type === 'click'));
}
}
function handleRedirects() {
const redirections = [...document.querySelectorAll('[data-activate-menu]'), ...document.querySelectorAll('[data-click-target]')];
redirections.forEach(function(element) {
const menuSelector = element.getAttribute('data-activate-menu') || element.getAttribute('data-click-target');
const redirectingElement = document.querySelector(menuSelector);
if (redirectingElement) {
element.style.cursor = 'pointer';
const redirect = function(e) {
if (redirectingElement.hasAttribute('href') || redirectingElement.hasAttribute('data-goto')) {
if (redirectingElement.hasAttribute('data-new-window') || e.ctrlKey || e.metaKey) {
window.open(getLink(redirectingElement), '_blank');
} else {
window.open(getLink(redirectingElement), '_self');
}
} else {
const evt = new e.constructor(e.type, e);
redirectingElement.dispatchEvent(evt);
}
};
element.addEventListener('mouseup', redirect);
element.addEventListener('mousedown', (e) => e.preventDefault());
element.addEventListener('click', (e) => e.preventDefault());
}
});
}
function handleMenus() {
const menuElements = [
...document.querySelectorAll('.header-menu > a'),
...document.querySelectorAll('.header-menu > p.menu-label')
];
let scrollYMemory = -1;
function scrollToMemory() {
if (scrollYMemory !== -1) {
setTimeout(function() {
window.scrollTo(0, scrollYMemory);
scrollYMemory = -1;
}, 10);
}
}
function hideMenus() {
// unfocus menus & items, and set the menus to non-visible.
menuElements.forEach(function (element) {
element.blur();
element.parentElement.blur();
element.parentElement.classList.remove('menu-opened');
const menuItems = element.parentElement.querySelector('.header-menu-items');
if (menuItems) {
menuItems.style.display = 'none';
}
});
const wasHidden = document.body.style.overflowY === 'hidden';
document.body.style.overflowY = 'auto';
if (wasHidden) {
scrollToMemory();
}
}
function isEventOutsideMenu(e) {
return e.target.closest && !e.target.closest('.header-menu') && !e.target.closest('[data-activate-menu]');
}
// Handle mobile menu toggling
menuElements.forEach(function(element) {
const menu = element.parentElement;
const headerItems = menu.querySelector('.header-menu-items');
const menuEntries = headerItems ? headerItems.querySelectorAll('.header-menu-item') : [];
const focus = function() {
menu.focus();
menu.classList.add('menu-opened');
if (headerItems) {
headerItems.style.display = 'block';
}
if (menu.classList.contains('zone-menu')) {
scrollYMemory = window.scrollY;
document.body.style.overflowY = 'hidden';
} else {
scrollYMemory = -1;
}
};
const unfocus = function() {
menu.blur();
menu.classList.remove('menu-opened');
if (headerItems) {
headerItems.style.display = 'none';
}
const wasHidden = document.body.style.overflowY === 'hidden';
document.body.style.overflowY = 'auto';
if (wasHidden) {
scrollToMemory();
}
};
const toggleMenuVisibility = function(e) {
if ((e.type === 'click' || e.type === 'mouseup') && !isLeftClick(e)) {
e.preventDefault();
return;
}
const hidden = isHidden(headerItems);
if (menu.hasAttribute('data-click-activation')) { // handle click activated toggling
if (hidden) {
hideMenus(); // hide other open menus first
focus();
} else {
unfocus();
}
e.preventDefault();
} else if (hidden) {
hideMenus(); // hide other open menus first
focus();
e.preventDefault(); // prevent 'click' event from firing when menu is hidden
}
};
element.addEventListener('touchend', toggleMenuVisibility);
element.addEventListener('mouseup', toggleMenuVisibility);
// Add hover events to non-click-activated menus, even though CSS should cover it.
if (!menu.hasAttribute('data-click-activation')) {
menu.addEventListener('mouseover', function () {
hideMenus(); // hide other open menus first
focus();
});
menu.addEventListener('mouseout', function (e) {
if (isEventOutsideMenu(e)) {
unfocus();
}
});
}
// Hide menu when child is clicked
menuEntries.forEach(function(menuEntry) {
const linkToItem = function(e) {
if (e.type === 'mousedown' || e.type === 'click') {
e.preventDefault();
return;
}
if (e.type === 'mouseup' && !isLeftClick(e)) {
e.preventDefault();
return;
}
window.open(getLink(menuEntry), (e.ctrlKey || e.metaKey) ? '_blank' : (menuEntry.target || '_self'));
unfocus();
e.preventDefault();
};
const linkToMobileItem = function(e) {
if (e.type === 'touchstart') {
menuEntry.setAttribute('data-touchmove', false);
} else if (e.type === 'touchmove') {
menuEntry.setAttribute('data-touchmove', true);
} else if (e.type === 'touchend' && (!menuEntry.hasAttribute('data-touchmove') || menuEntry.getAttribute('data-touchmove').toLowerCase() === 'false')) {
window.open(getLink(menuEntry), (e.ctrlKey || e.metaKey) ? '_blank' : (menuEntry.target || '_self'));
unfocus();
e.preventDefault();
}
};
menuEntry.addEventListener('mousedown', linkToItem);
menuEntry.addEventListener('mouseup', linkToItem);
menuEntry.addEventListener('click', linkToItem);
menuEntry.addEventListener('touchstart', linkToMobileItem);
menuEntry.addEventListener('touchmove', linkToMobileItem);
menuEntry.addEventListener('touchend', linkToMobileItem);
});
});
function hideIfNonMenuBounds(e) {
if (isEventOutsideMenu(e)) {
hideMenus();
}
}
addEventListener('mousemove', hideIfNonMenuBounds);
addEventListener('touchend', hideIfNonMenuBounds);
addEventListener('mouseup', hideIfNonMenuBounds);
addEventListener('mousedown', hideIfNonMenuBounds);
addEventListener('click', hideIfNonMenuBounds);
}
function handleMobileMenuHeights() {
function setAppHeight() {
document.documentElement.style.setProperty('--app-height', window.innerHeight + 'px');
}
addEventListener('resize', function() {
setAppHeight();
});
setAppHeight();
}
function handleGotoLinks() {
// Add anchor mimicking to elements with data-goto attributes
// This addresses SEO concerns of linking to noindex pages by allowing JS to handle the URL
const anchorElements = document.querySelectorAll('*[data-goto]');
anchorElements.forEach((anchorElement) => {
anchorElement.addEventListener('mouseover', () => {
anchorElement.style.cursor = 'pointer';
anchorElement.style.textDecoration = 'underline';
});
anchorElement.addEventListener('mouseout', () => {
anchorElement.style.cursor = 'unset';
anchorElement.style.textDecoration = 'unset';
});
anchorElement.addEventListener('mouseup', (e) => {
e.preventDefault();
});
anchorElement.addEventListener('mousedown', (e) => {
e.preventDefault();
});
anchorElement.addEventListener('click', (e) => {
e.preventDefault();
const anchorHref = anchorElement.getAttribute('data-goto');
if (anchorElement.hasAttribute('data-new-window') || e.ctrlKey || e.metaKey) {
window.open(anchorHref, '_blank');
} else {
window.open(anchorHref, '_self');
}
});
});
}
</script><script>
const authenticatedBlock = document.querySelector('#authenticated-block');
const unauthenticatedBlock = document.querySelector('#unauthenticated-block');
let authenticated = {
isAuthenticated: false,
isAdmin: false,
user: {
id: null,
name: null,
url: null,
profileImage: null,
}
};
fetch('/services/internal/data/articles-getAuthenticationStatus', {
headers: {
'Accept': 'application/json'
}
})
.then(function (result) {
return result.json()
})
.then(function (result) {
const res = result.result.data
if (!res.authenticated) {
unauthenticatedBlock.classList.add('shown')
} else {
authenticated.user.id = res.id;
authenticated.user.name = res.realName;
authenticated.user.url = res.profileUrl;
authenticated.user.profileImage = res.avatar;
authenticated.user.jobTitle = res.jobTitle;
authenticated.user.companyName = res.companyName;
bindProps('#header-username', null, null, (res.firstName || res.username), null)
bindProps('#header-avatar', null, res.avatar, null, null)
bindProps('#header-user-plug', res.profileUrl, null, res.realName, null)
bindProps('#header-user-edit', '/users/' + res.id + '/edit.html', null, null, null)
bindProps('#header-dropdown-manage-email', '/newsletters/' + res.id + '/manage.html', null, null, null)
bindProps('#dropdown-view-profile', res.profileUrl, null, null, null)
bindProps('#drafts-link', '/users/' + res.id + '/drafts.html', null, null, null)
if (res.isAdmin) {
// Construct backwards so the #after call places elements in the correct order
const firstUserAction = document.querySelector('#first-user-action')
const adminConsoleItem = document.createElement('li')
const adminConsoleLink = createLink('/dzone/staff/index.html', 'Admin Console')
adminConsoleItem.appendChild(adminConsoleLink)
firstUserAction.after(adminConsoleItem)
const moderationItem = document.createElement('li')
const moderationLink = createLink('/moderation/list.html', 'Moderation')
moderationItem.appendChild(moderationLink)
firstUserAction.after(moderationItem)
const bountyModerationItem = document.createElement('li')
const bountyModerationLink = createLink('/moderation/bounties', 'Bounty Moderation')
bountyModerationItem.appendChild(bountyModerationLink)
firstUserAction.after(bountyModerationItem)
}
authenticated.isAuthenticated = res.authenticated;
authenticated.isAdmin = res.isAdmin;
authenticatedBlock.classList.add('shown')
}
}).catch(function (result) {
console.error(result)
})
/**
* Binds different properties to the selected element.
*
* @param selector - Selector to select the element
* @param href - href attribute value
* @param src - src attribute value
* @param innerHTML - innerHTML property value
* @param innerText - innerText property value
*/
function bindProps(selector, href, src, innerHTML, innerText) {
const element = document.querySelector(selector)
if (element) {
if (href) element.href = href
if (src) element.src = src
if (innerHTML) element.innerHTML = innerHTML
if (innerText) element.innerText = innerText
}
}
/**
* Creates a new link element.
*
* @param href - href attribute value
* @param innerText - innerText property value
* @returns {HTMLAnchorElement} The generated link element
*/
function createLink(href, innerText) {
const link = document.createElement('a')
link.href = href
link.innerText = innerText
return link
}
</script><script>
const userHeader = document.querySelector('#user-header')
const userDropdown = document.querySelector('#user-dropdown')
const postDropdown = document.querySelector('#post-button')
const postMenu = document.querySelector('#post-menu')
let userDropdownOpen = false
let postDropdownOpen = false
document.addEventListener('click', function(event) {
if (postDropdown && postDropdown.contains(event.target)) {
setUserDropdown(false)
setPostDropdown(!postDropdownOpen)
} else if (userHeader && userHeader.contains(event.target)) {
setPostDropdown(false)
setUserDropdown(!userDropdownOpen)
} else {
setUserDropdown(false)
setPostDropdown(false)
}
})
function setUserDropdown(value) {
userDropdownOpen = value
if (userDropdownOpen) {
if (userDropdown) {
userDropdown.classList.add('open')
}
} else {
if (userDropdown) {
userDropdown.classList.remove('open')
}
}
}
function setPostDropdown(value) {
postDropdownOpen = value
if (postDropdownOpen) {
if (postMenu) {
postMenu.classList.add('open')
}
} else {
if (postMenu) {
postMenu.classList.remove('open')
}
}
}
</script><script>
document.addEventListener("alpine:init", () => {
Alpine.store('global', {
executeHttp(path, body, method) {
const options = {
method: method,
headers: {
[csrf.header]: csrf.token
}
};
if (method !== 'GET') {
options.body = JSON.stringify(body);
options.headers = {
...options.headers,
'Content-Type': 'application/json; charset=UTF-8'
};
}
return new Promise((resolve, reject) => {
fetch(path, options)
.then(res => {
if (!res.ok) {
reject(res);
} else {
resolve(res);
}
})
.catch(err => reject(err));
});
},
getFromService(path) {
return this.executeHttp(path, null, 'GET');
},
postToService(path, body = {}) {
return this.executeHttp(path, body, 'POST');
},
putToService(path, body = {}) {
return this.executeHttp(path, body, 'PUT');
}
});
});
</script>
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/colors.css">
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/article/styles.css">
<div id="body-container">
<div id="announcement-container-outer">
<div id="announcement-previous">
<i class="icon-angle-left"></i>
</div>
<div id="announcement-next">
<i class="icon-angle-right"></i>
</div>
<div id="announcement-container">
<div class="announcement announcement-count-1"
data-position="1">
<div class="body"><p><strong>Could your team report a vulnerability within 24 hours? </strong>Find out on September 23.</p></div>
<div class="spacer"></div>
<a href="https://cvent.me/O32zXR?utm_source=Announcements&amp;utm_medium=DzoneWeb&amp;utm_campaign=QtGroup-0923" target="_blank">
<button>Assess Your CRA Readiness</button>
</a>
</div>
</div>
</div>
<script type="text/javascript" async>
(function() {
let announcementPosition = 1;
let minAnnouncementPosition = -1;
let maxAnnouncementPosition = -1;
const announcementPrevBtn = document.querySelector('#announcement-previous');
const announcementNextBtn = document.querySelector('#announcement-next');
function withAnnouncements(callback) {
const announcements = document.querySelectorAll('#announcement-container .announcement');
for (let announcement of announcements) {
callback(announcement);
}
}
function initAnnouncementVars() {
document.querySelector(':root').style.setProperty('--mobile-announcement-separator-width', '1px');
withAnnouncements(function(announcement) {
const pos = parseInt(announcement.getAttribute('data-position'));
minAnnouncementPosition = minAnnouncementPosition === -1 ? pos : Math.min(minAnnouncementPosition, pos);
maxAnnouncementPosition = maxAnnouncementPosition === -1 ? pos : Math.max(maxAnnouncementPosition, pos);
});
if (document.querySelector('.announcementBarContainer')) {
document.querySelector(':root').style.setProperty('--body-top-padding', '0');
}
if (maxAnnouncementPosition <= 0) {
document.querySelector(':root').style.setProperty('--body-top-padding', '0');
}
sizeToFullWhenOneEntryOnMobile();
}
function setAnnouncementPosition(position) {
if (window.outerWidth >= 890) {
return; // we do not need to change the position, since we can display everything on desktop.
}
// Make the announcement cyclical
if (minAnnouncementPosition !== -1 && maxAnnouncementPosition !== -1) {
if (position > maxAnnouncementPosition) {
position = minAnnouncementPosition; // overflow to the first announcement
} else if (position < minAnnouncementPosition) {
position = maxAnnouncementPosition; // underflow to the last announcement
}
announcementPosition = position;
}
const shownAnnouncements = [];
let reverseFlex = false; // should only be true when the first and last items are showing
// Now that the position is valid, apply the transforms
withAnnouncements(function(announcement) {
const pos = parseInt(announcement.getAttribute('data-position'));
const isWrapped = position === maxAnnouncementPosition && pos === minAnnouncementPosition; // showing first + last at same time
const doesNextQualify = window.outerWidth >= 500 && (pos === position + 1 || isWrapped);
if (pos === position || doesNextQualify) {
shownAnnouncements.push(announcement);
} else {
announcement.style.display = 'none';
}
announcement.style.opacity = 0.0;
if (isWrapped) {
reverseFlex = true;
}
});
for (let announcement of shownAnnouncements) {
announcement.style.display = 'flex';
announcement.style.opacity = 1.0;
}
const announcementContainer = document.querySelector('#announcement-container');
if (announcementContainer) {
announcementContainer.style.flexDirection = reverseFlex ? 'row-reverse' : 'row';
}
}
function resetAnnouncements() {
announcementPosition = 1;
const announcementContainer = document.querySelector('#announcement-container');
if (announcementContainer) {
announcementContainer.style.flexDirection = 'row';
}
withAnnouncements(function(announcement) {
announcement.style.opacity = 1.0;
announcement.style.display = 'flex';
});
}
function sizeToFullWhenOneEntryOnMobile() {
if (maxAnnouncementPosition <= 2 && announcementPrevBtn && announcementNextBtn) {
announcementPrevBtn.style.display = maxAnnouncementPosition === 2 && window.outerWidth < 500 ? 'flex' : 'none';
announcementNextBtn.style.display = maxAnnouncementPosition === 2 && window.outerWidth < 500 ? 'flex' : 'none';
}
if (maxAnnouncementPosition === 1 && window.outerWidth >= 500 && window.outerWidth < 890) {
document.querySelector(':root').style.setProperty('--mobile-announcement-separator-width', '0');
document.querySelector('#announcement-container .announcement').style.maxWidth = '100%';
}
}
function resetAnnouncementsOnResize() {
announcementPosition = 1; // we want to reset the announcement position every resize
if (window.outerWidth >= 890) { // 4 announcements can be shown (215px * 4) + separator padding
resetAnnouncements();
} else { // if we're still on mobile, set the position to normalize things after resize
setAnnouncementPosition(announcementPosition);
sizeToFullWhenOneEntryOnMobile();
}
}
window.addEventListener('resize', resetAnnouncementsOnResize);
initAnnouncementVars();
setAnnouncementPosition(announcementPosition); // sets the min & max positions as well as initializes transforms
if (announcementPrevBtn) {
announcementPrevBtn.onclick = function() {
setAnnouncementPosition(announcementPosition - 1);
};
}
if (announcementNextBtn) {
announcementNextBtn.onclick = function() {
setAnnouncementPosition(announcementPosition + 1);
};
}
})(); </script>
<div id="ftl-article" class="trending-article-body">
<aside class="trending-sidebar" aria-labelledby="related-sidebar-heading">
<div class="trending">
<h2 id="related-sidebar-heading">Related</h2>
<div class="trending-separator"></div>
<ul>
<li class="item">
<a href="/articles/cloud-automation-excellence-terraform-ansible-amp" class="related-link">Cloud Automation Excellence: Terraform, Ansible, and Nomad for Enterprise Architecture</a>
</li>
<li class="item">
<a href="/articles/unlock-the-power-of-terragrunts-hierarchy" class="related-link">Unlock the Power of Terragrunt’s Hierarchy</a>
</li>
<li class="item">
<a href="/articles/how-to-reduce-the-impact-of-a-cloud-outage" class="related-link">How To Reduce the Impact of a Cloud Outage</a>
</li>
<li class="item">
<a href="/articles/ai-cloud-infrastructure" class="related-link">Why Traditional Cloud Infrastructure Breaks AI Workloads in Production</a>
</li>
</ul>
</div>
</aside>
<div class="container-fluid body trending-article-fluid">
<div class="row">
<div class="col-md-12">
<div class="articles-wrap">
<div class="ad-container">
<div id="div-gpt-ad-1435246566686-0" class="ads-billboard-article dz2_article_billboard_new" data-gpt-slot="top"></div>
</div>
<div class="article-stream widget-top-border">
<div class="article-main">
<div class="content-right-images">
<div id="div-gpt-ad-1435246566686-2" class="sidebar-ad dz2_article_halfpage_new" data-gpt-slot="sidebar1"></div>
<div class="trending-separator"></div>
<aside class="trending" aria-labelledby="trending-sidebar-heading">
<h2 id="trending-sidebar-heading">Trending</h2>
<ul>
<li class="item">
<a href="/articles/email-security-dns" class="trending-link" target="_self">Your Email Security Is a DNS Configuration Problem</a>
</li>
<li class="item">
<a href="/articles/excel-dynamic-arrays-java" class="trending-link" target="_self">Dynamic Arrays, Spill, and LET: What Changed in Excel and Why It Matters for Java Applications</a>
</li>
<li class="item">
<a href="/articles/prompting-ai-for-analytics" class="trending-link" target="_self">Prompting AI for Analytics: The Missing Optimization Layer Between Your Question and the Model</a>
</li>
<li class="item">
<a href="/articles/mcp-for-enterprise-tasks" class="trending-link" target="_self">MCP for Enterprise Tasks: Making the Rare Frequent Enough to Master</a>
</li>
</ul>
</aside>
</div>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Mutable vs. Immutable: Infrastructure Models in the Cloud Era",
"author": [{"image":{"@type":"ImageObject","caption":"Josephine Eskaline Joyce, Ph.D","url":"https://secure.gravatar.com/avatar/2b9e5d94e87288f4e57a6a14708f0aae?d=identicon&r=PG"},"@type":"Person","worksFor":{"@type":"Organization","name":"IBM"},"name":"Josephine Eskaline Joyce, Ph.D","description":"Josephine Eskaline Joyce is an STSM and Chief Architect at IBM with more than 25 years of experience in designing and advancing enterprise cloud architectures, platform engineering solutions, and security-first cloud practices. Her expertise spans Infrastructure as Code, AI-driven automation, resilient DevOps, cloud security, and scalable cloud-native platforms. She is an IBM Master Inventor with patented innovations and has authored research articles on cloud-native systems, automation, artificial intelligence, and emerging technologies. The views expressed here are solely her own.","url":"https://dzone.com/authors/jojustin","sameAs":["https://github.com/jojustin","https://www.linkedin.com/in/josephine-joyce/"]},{"image":{"@type":"ImageObject","caption":"Umar Ali","url":"https://secure.gravatar.com/avatar/b32a1a7f27266a82fcb42cbd28ed5e01?d=identicon&r=PG"},"@type":"Person","worksFor":{"@type":"Organization","name":"IBM"},"name":"Umar Ali","url":"https://dzone.com/users/5219734/ushaik.html"}],
"audience": "software developers",
"keywords": "",
"timeRequired": "PT10M",
"commentCount": 0,
"wordCount": "2493",
"accessMode": "textual, visual",
"datePublished": "2024-10-14T00:00:00Z",
"articleSection": "",
"publisher": {
"@type": "Organization",
"name": "DZone",
"url": "https://dzone.com",
"logo": {
"@type": "ImageObject",
"url": "https://dzone.com/themes/dz20/images/dz_logo_2021_cropped.png"
}
},
"articleBody": "In the world of infrastructure management, two fundamental approaches govern how resources are deployed and maintained: mutable and immutable infrastructure. These approaches influence how updates are made, how infrastructure evolves, and how consistency is ensured across different environments. Mutable infrastructure refers to systems that can be changed or updated after they’ve been initially deployed. This means that configuration changes, software updates, or patches can be applied directly to existing infrastructure resources without replacing them entirely. For instance, a server can be updated by installing new software, tweaking its settings, or increasing its resources. While the server itself stays the same, its configuration evolves over time. Immutable infrastructure works differently. Once it’s deployed, it can’t be changed or updated. Instead of modifying what’s already there, any updates or changes require replacing the existing infrastructure with a new version that includes the updates. For example, if a new version of an application needs to be deployed, new servers are created with the updated settings, while the old servers are shut down or removed. This approach ensures consistency with each deployment and avoids any unexpected issues from lingering changes. Key Differences Between Mutable and Immutable Infrastructure When comparing mutable and immutable infrastructure, several key differences highlight the strengths and trade-offs of each approach. These differences revolve around how changes are handled, how infrastructure consistency is maintained, and the overall impact on operations. Use Case Mutable Infrastructure Immutable Infrastructure Change Management Allows in-place updates, where changes, updates, or patches can be applied directly to running infrastructure without redeploying. This can be faster and more convenient for making incremental adjustments. Does not allow in-place changes. Instead, any update requires the creation of a new instance or infrastructure. The old instance is terminated after the new one is successfully deployed. Changes happen by replacing the infrastructure entirely. Configuration Drift Prone to configuration drift. Over time, as small changes are applied to systems manually or through different tools, the configuration of the system can deviate from its original state. This makes it harder to maintain consistency. Eliminates configuration drift. Every deployment starts fresh with a new environment, ensuring that the infrastructure always matches the desired state and behaves consistently. Consistency May lead to inconsistencies if manual changes are made, or if different versions of updates are applied across environments. This can result in unexpected behavior, particularly in environments that are long-lived or frequently updated. Highly consistent because each deployment uses a clean state. This ensures that each instance of the infrastructure are same, avoiding unexpected issues from differing configurations. Downtime Can be updated in-place, which often leads to shorter or no downtime. This is crucial for systems that require high availability and cannot afford to be redeployed. May involve temporary downtime during the replacement process, depending on the strategy used (e.g., blue-green or rolling deployments). However, modern techniques like blue-green or canary deployments can mitigate this issue by seamlessly transitioning between old and new infrastructure. Rollback Complexity Rolling back changes can be complex because reverting to a previous configuration may not fully restore the infrastructure to its original state. In most cases, manual intervention may be required. Rollback is simpler. Since new infrastructure is created for every change, rolling back is as easy as redeploying the previous, working version. This reduces the risk of failure when reverting to an earlier state. Security Security patches are applied directly to running systems, which can leave them vulnerable to attack if patches are delayed or improperly applied. Manual patching introduces risks. More secure because each update replaces the entire system with a fresh instance. This ensures that any vulnerabilities from previous configurations are completely removed, and patched versions are consistently applied. Operational Overhead Requires more maintenance and monitoring to ensure that updates are properly applied and systems remain secure over time. This can increase operational overhead, especially when managing large, complex environments. Reduces operational overhead by standardizing updates and deployments. Since there’s no need to manage in-place updates, less effort is required to maintain consistency across environments. Resource Efficiency More resource-efficient in some cases since updates are made to the existing resources without creating new ones. This can save costs and time, especially for updates that don’t require full system redeployment. Requires the creation of new resources for every update, which can lead to increased costs and resource usage, particularly for environments that need frequent updates or scaling. However, automation tools can help manage this process more efficiently. Use Cases Suited for environments where rapid, in-place updates are needed without full redeployment (e.g., databases, development and testing environments, or legacy systems). It’s also practical for environments where costs need to be minimized by reusing existing infrastructure. Best for environments where consistency, security, and reliability are critical, such as production environments, containerized applications, and microservices. Immutable infrastructure is ideal for organizations that prioritize automation, scaling, and continuous delivery. Infrastructure Lifespan Often associated with long-lived infrastructure where the same resources are maintained and updated over time. These systems may evolve as they stay active, leading to drift over time. Typically associated with short-lived infrastructure. Resources are frequently replaced with newer versions, reducing the need for ongoing maintenance of the same system. When to Choose Mutable Infrastructure While immutable infrastructure is often preferred in modern environments due to its consistency and reliability, there are still several scenarios where choosing mutable infrastructure is more practical and beneficial. Mutable infrastructure offers flexibility for certain use cases where in-place changes, cost-effectiveness, or maintaining long-lived systems are essential. Here are some key situations where you should consider using mutable infrastructure: Dynamic or evolving environments - In scenarios where the infrastructure needs to frequently adapt to changes, such as in development or testing environments, mutable infrastructure is advantageous. Developers may need to quickly update configurations, modify code, or patch resources without spinning up new instances.Cost-sensitive environments - Immutable infrastructure can increase operational costs, particularly in cloud environments where spinning up new instances for every update incurs additional expenses. For cost-sensitive environments, such as startups or organizations with tight budgets, mutable infrastructure can be more economical.Stateful applications - Applications or services that maintain state (such as databases, file systems, or session-oriented services) benefit from mutable infrastructure. In these cases, tearing down and replacing infrastructure can lead to data loss or significant complexity in preserving state.Legacy systems - Legacy systems often rely on mutable infrastructure due to their architecture and the fact that they weren’t designed with modern immutable practices in mind. Rewriting or migrating legacy applications to immutable infrastructure may be impractical, expensive, or risky, making mutable infrastructure the better choice.Applications with infrequent updates - For environments or applications where updates are infrequent and the risk of configuration drift is low, mutable infrastructure can be a simple and effective solution. If the system doesn’t require constant adjustments or scaling, maintaining long-lived infrastructure may be sufficient.Systems that require minimal downtime - Some critical systems cannot afford the downtime that might occur during the replacement of infrastructure, especially in high-availability environments. Mutable infrastructure allows for in-place updates, which can minimize or eliminate downtime altogether.Systems with complex interdependencies - In environments where services or applications have complex interdependencies, managing immutable infrastructure might become difficult. When numerous components rely on each other, applying changes in place ensures those connections remain intact without needing to redeploy the entire infrastructure. When to Choose Immutable Infrastructure Immutable infrastructure has become a popular approach in today's IT world, especially in cloud-native and DevOps environments. It helps prevent configuration drift and guarantees consistent, reliable deployments. However, it's not always the best fit for every situation. There are cases where choosing immutable infrastructure is highly advantageous, particularly when consistency, security, and scalability are crucial priorities. Here are key situations where choosing immutable infrastructure is the better choice: Production environments - Immutable infrastructure works exceptionally well in production environments where stability and reliability are key. By avoiding in-place changes, it keeps the production environment consistent and minimizes the risk of unexpected errors from manual updates or configuration drift. This makes it a solid choice when maintaining a reliable system is essential.Security-conscious environments - In environments where security is a top priority, immutable infrastructure is a more secure option. Since no manual changes are applied after the infrastructure is deployed, there’s less risk of introducing vulnerabilities through untracked or insecure changes.Microservices architectures - Microservices architectures are built to be modular, making it easy to replace individual components. In these setups, immutable infrastructure plays a key role by ensuring each service is deployed consistently and independently, helping to avoid the risk of misconfigurations. This approach enhances reliability across the system. CI/CD pipelines and automation - Continuous Integration and Continuous Delivery (CI/CD) pipelines thrive on consistency and automation. Immutable infrastructure complements CI/CD pipelines by ensuring that every deployment is identical and repeatable, reducing the chances of failed builds or broken environments.Disaster recovery and rollbacks - Immutable infrastructure simplifies disaster recovery and rollbacks. Since infrastructure is not modified after deployment, rolling back to a previous version is as simple as redeploying the last known working configuration. This reduces downtime and makes recovery faster and more reliable.Scalability and auto-scaling - In environments where scalability is a key requirement, immutable infrastructure supports automatic scaling by creating new instances as needed, rather than modifying existing ones. This is particularly useful for cloud-native applications or containerized environments where dynamic scaling is a common requirement.Blue-green or canary deployments - Blue-green and canary deployment strategies are ideal candidates for immutable infrastructure. These deployment methods rely on running two environments simultaneously (blue and green), where the new version is tested before it fully replaces the old one.Cloud-native and containerized applications - Cloud-native and containerized applications naturally align with immutable infrastructure because they are designed to be stateless, scalable, and disposable. Infrastructure as Code (IaC) tools like Terraform, combined with container orchestration platforms like Kubernetes, benefit greatly from immutable practices.High-availability systems - High-availability systems that cannot tolerate downtime can benefit from immutable infrastructure. With rolling or blue-green deployments, updates are applied seamlessly, ensuring that there is no disruption to the end user. Hybrid Approaches: Combining Mutable and Immutable Infrastructure While immutable infrastructure offers reliability and consistency, and mutable infrastructure provides flexibility and state retention, many organizations can benefit from a hybrid approach. By combining the best of both models, you can build a more flexible infrastructure that adapts to the specific needs of different components in your environment. This balanced approach allows you to address varying requirements more effectively. A hybrid approach typically involves using immutable infrastructure for stateless services, where consistency and repeatability are essential, and mutable infrastructure for stateful services or legacy systems, where preserving data and flexibility is more important. Terraform, as a powerful Infrastructure as Code (IaC) tool, can manage both models simultaneously, giving you the flexibility to implement a hybrid approach effectively. Use Immutable Infrastructure for Stateless Components Stateless services and applications that don’t rely on maintaining internal state across sessions are ideal for immutable infrastructure. These services can be replaced or scaled without the need for in-place updates. Example: With Terraform, you can manage web server deployments behind a load balancer seamlessly. Each time the application is updated, new instances are deployed while the old ones are removed. This ensures that the web servers are always running the latest version of the application, without any risk of configuration drift. Use Mutable Infrastructure for Stateful Components Stateful components, such as databases, file systems, or applications that retain session data, require mutable infrastructure to preserve the data across updates. Replacing these components in an immutable model would involve complex data migration and could risk data loss. Example: Manage a relational database like PostgreSQL using Terraform, where you need to update storage capacity or apply security patches without replacing the database instance. This ensures that the data remains intact while the infrastructure is modified. Automate Infrastructure Management With Terraform Terraform’s ability to define infrastructure as code allows you to automate both mutable and immutable deployments. With a hybrid approach, you can use Terraform to manage both types of infrastructure side by side, ensuring consistency where needed and flexibility where required. Example: Use Terraform to define both immutable and mutable resources in a single deployment plan. For example, use immutable infrastructure for auto-scaling application servers, while managing stateful databases with mutable infrastructure for in-place updates. Implement Hybrid Scaling Strategies In environments with both stateless and stateful services, scaling strategies can benefit from a hybrid approach. Stateless services can be scaled horizontally using immutable infrastructure, while stateful services may require vertical scaling or more complex approaches. Example: Use Terraform to manage auto-scaling groups for stateless web servers while adjusting database resources (such as memory or CPU) for stateful services through mutable infrastructure. This ensures that both types of services can scale based on their unique needs. Legacy System Modernization Many organizations have legacy systems that are critical to their operations but are not easily moved to an immutable infrastructure model. In these cases, a hybrid approach allows organizations to maintain these legacy systems with mutable infrastructure while using immutable infrastructure for newer, cloud-native components. Example: Use Terraform to manage infrastructure for both legacy and modern applications. The legacy system (e.g., an on-premises ERP) can be maintained with mutable infrastructure, while cloud-native microservices are deployed with immutable infrastructure in the cloud. Simplifying Disaster Recovery With Hybrid Approaches A hybrid approach can simplify disaster recovery by leveraging the benefits of both models. Immutable infrastructure can be used for services that need quick rollbacks, while mutable infrastructure can handle systems that need to retain their state after recovery. Example: In a hybrid cloud environment managed by Terraform, stateless services (like a front-end application) can be redeployed quickly with immutable infrastructure, while stateful services (like a database) can be restored from backups using mutable infrastructure. Security and Compliance Considerations Security-sensitive applications benefit from immutable infrastructure due to the reduction in configuration drift and manual changes. However, some services, especially those involving sensitive data (like customer databases), may require mutable infrastructure for security patching and retention of critical state information. Also it is important to note that the evidence is updated when immutable infrastructure are used. Example: Use immutable infrastructure for API gateways and front-end services to ensure they are always deployed with the latest security patches. Simultaneously, manage the back-end databases using mutable infrastructure, allowing for in-place security patches without affecting stored data.Example: Terraform can be used to manage testing environments with immutable infrastructure, ensuring that each test is performed on a fresh, consistent environment. Meanwhile, long-lived production databases are managed with mutable infrastructure, allowing for updates and scaling without disruption. Conclusion A hybrid approach to infrastructure combines the best of both mutable and immutable models, offering flexibility for stateful and legacy systems while ensuring consistency and scalability for stateless services. By using Terraform to manage this blend, organizations can optimize their infrastructure for dynamic needs, balancing reliability, cost-efficiency, and operational flexibility. This approach allows for tailored strategies that meet the unique demands of various applications and services.",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "https://dzone.com/articles/infrastructure-models-in-the-cloud-era"
},
"image": {
"@type": "ImageObject",
"url": "https://dz2cdn1.dzone.com/storage/article-thumb/17974679-thumb.jpg"
}
}
</script>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "DZone",
"item": "https://dzone.com"
},
{
"@type": "ListItem",
"position": 2,
"name": "Software Design and Architecture",
"item": "https://dzone.com/software-design-and-architecture"
},
{
"@type": "ListItem",
"position": 3,
"name": "Cloud Architecture",
"item": "https://dzone.com/cloud-architecture"
},
{
"@type": "ListItem",
"position": 4,
"name": "Mutable vs. Immutable: Infrastructure Models in the Cloud Era",
"item": "https://dzone.com/articles/infrastructure-models-in-the-cloud-era"
}
]
}
</script>
<article>
<div class="content">
<div class="header">
<ol class="breadcrumb">
<li class="server"><a href="https://dzone.com">DZone</a></li>
<li class="server"><a href="https://dzone.com/software-design-and-architecture">Software Design and Architecture</a></li>
<li class="server"><a href="https://dzone.com/cloud-architecture">Cloud Architecture</a></li>
<li class="active server">Mutable vs. Immutable: Infrastructure Models in the Cloud Era</li>
</ol>
<div class="header-title">
<div class="title">
<h1 class="article-title">Mutable vs. Immutable: Infrastructure Models in the Cloud Era</h1>
</div>
<div class="subhead">
<p>Explore mutable infrastructure and immutable structures: learn which offers flexibility for updates, consistency, reliability, and fits different cloud needs.</p>
</div>
<div class="publish-meta">
By<span style="user-select: none;">&nbsp;</span>
<div class="article-author-meta">
<img src="https://dz2cdn1.dzone.com/thumbnail?fid=17052212&w=80" class="avatar" alt="Josephine Eskaline Joyce, Ph.D user avatar" width="40">
<div class="author-info">
<span class="author-name">
<a href="/authors/jojustin" data-core-user="true">Josephine Eskaline Joyce, Ph.D</a>
</span>
</div>
<span class="badge-container badge-text-md">
<img class="author-core-badge" width="18" height="18" alt="DZone Core" src="https://dz2cdn1.dzone.com/themes/dz20/images/dz-core-icon.png" style="margin: 0 0 3px 2px">
CORE
</span>
&middot;
</div>
<div class="article-author-meta">
<img src="https://dz2cdn1.dzone.com/thumbnail?fid=17984617&w=80" class="avatar" alt="Umar Ali user avatar" width="40">
<div class="author-info">
<span class="author-name">
<a href="/users/5219734/ushaik.html" rel="nofollow" data-core-user="false">Umar Ali</a>
</span>
</div>
&middot;
</div>
<span class="author-date">
Oct. 14, 24
</span>
&middot;
<span>Analysis</span>
</div>
</div>
</div>
<div class="author-n-useraction">
<div class="like action" x-data="engagementModal(articleId)">
<span id="activity-like-icon" class="dz-like icon-thumbs-up" x-on:click="updateStore()"></span>
<span class="action-label like-text" x-on:click="open()" x-cloak>
<span>Likes</span>
<span id="activity-like-counter" class="like-count">(4)</span>
</span>
<template x-teleport="body">
<div class="engagement-overlay" x-show="$store.article.engagement.open && nodeId === $store.article.id" x-on:keyup.escape.window="close()">
<div class="engagement-modal">
<div class="inner" x-on:click.outside="close()">
<div class="header">
<div class="title">Likes</div>
<button class="close" x-on:click="close()"></button>
</div>
<div class="content">
<div x-show="$store.article.engagement.initializing" class="loading-screen">
<i class="icon icon-spin3 anim-spin"></i>
</div>
<div x-show="!$store.article.engagement.initializing">
<template x-for="user in $store.article.engagement.users" :key="user.id">
<div class="media">
<div class="media-left">
<img class="avatar"
x-bind:src="user.profile.profileImage"
loading="lazy"
width="50"
height="50"
>
</div>
<div class="media-right">
<a x-bind:href="user.computed.url" x-html="user.profile.name"></a>
<div x-show="formatJobData(user)" x-html="formatJobData(user)"></div>
</div>
</div>
</template>
</div>
<div x-show="isDataUnavailable()" class="center-screen">
<div x-show="!$store.article.engagement.unauthorized">
<div>There are no likes...yet! &#128064;</div>
<div>Be the first to like this post!</div>
</div>
<div x-show="$store.article.engagement.unauthorized">
<div>It looks like you're not logged in.</div>
<div><a href="/users/login.html">Sign in</a> to see who liked this post!</div>
</div>
</div>
<div x-show="isFooterShowing()">
<div class="footer">
<button class="btn btn-primary" x-on:click="fetchEngagements()"
x-bind:disabled="$store.article.engagement.loading"
>
Load More
<i x-show="$store.article.engagement.loading" class="icon icon-spin3 anim-spin"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template> </div>
<div class="action comment-action">
<span class="comment">
<i class="icon-comment"></i>
<span class="action-label">Comment</span>
<span id="activity-comment-counter" class="comment-count"></span>
</span>
</div>
<div class="save action">
<div id="activity-save-icon" class="save icon-star-empty">
<span id="activity-save-text" class="action-label">Save</span>
</div>
</div>
<div class="tweet action">
<a id="tweet-link" href="" class="title" target="_blank">
<span><i class="icon-twitter"></i></span>
<span class="action-label">Tweet</span>
</a>
</div>
<div class="linkedin action">
<a id="linkedin-link" href="https://www.linkedin.com/sharing/share-offsite/?url=https://dzone.com/articles/infrastructure-models-in-the-cloud-era" class="title" target="_blank">
<span><i class="icon-linkedin-1"></i></span>
<span class="action-label">Share</span>
</a>
</div>
<div class="right-most">
<div id="activity-view-container" class="article-views action">
<i class="icon-eye"></i>
<span class="action-label view-count">11.6K Views</span>
</div>
</div>
</div>
<div class="signin-prompt">
<p>Join the DZone community and get the full member experience.</p>
<a id="article-signin-prompt" href="/static/registration.html">Join For Free</a>
</div>
<div class="arrow-down"></div>
<div id="top-bumper-container"></div>
<div>
<div class="content-html"><p style="text-align: left;">In the world of infrastructure management, two fundamental approaches govern how resources are deployed and maintained: <a href="https://www.hashicorp.com/resources/what-is-mutable-vs-immutable-infrastructure" rel="noopener noreferrer" target="_blank"><strong>mutable</strong> and <strong>immutable infrastructure</strong></a>. These approaches influence how updates are made, how infrastructure evolves, and how consistency is ensured across different environments.</p>
<p style="text-align: left;">Mutable infrastructure refers to systems that can be changed or updated after they’ve been initially deployed. This means that configuration changes, software updates, or patches can be applied directly to existing infrastructure resources without replacing them entirely. &nbsp;For instance, a server can be updated by installing new software, tweaking its settings, or increasing its resources. While the server itself stays the same, its configuration evolves over time.</p>
<p style="text-align: left;">Immutable infrastructure works differently. Once it’s deployed, it can’t be changed or updated. Instead of modifying what’s already there, any updates or changes require replacing the existing infrastructure with a new version that includes the updates. For example, if a new version of an application needs to be deployed, new servers are created with the updated settings, while the old servers are shut down or removed. This approach ensures consistency with each deployment and avoids any unexpected issues from lingering changes.</p>
<h2 style="text-align: left;">Key Differences Between Mutable and Immutable Infrastructure</h2>
<p style="text-align: left;">When comparing mutable and immutable infrastructure, several key differences highlight the strengths and trade-offs of each approach. These differences revolve around how changes are handled, how infrastructure consistency is maintained, and the overall impact on operations.</p>
<div class="table-responsive" style="border: none; text-align: justify;">
<table style="max-width: 100%; width: auto; table-layout: fixed; display: table;" width="auto">
<thead>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<th style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>Use Case</strong>
</div></th>
<th style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>Mutable Infrastructure</strong>
</div></th>
<th style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>Immutable Infrastructure</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<a href="https://dzone.com/articles/adaptive-change-management"><strong>Change Management</strong></a>
</div>
<div data-empty="true" style="text-align: left;">
<br>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
Allows <strong>in-place updates</strong>, where changes, updates, or patches can be applied directly to running infrastructure without redeploying. This can be faster and more convenient for making incremental adjustments.
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<p style="text-align: left;">Does <strong>not allow in-place changes.</strong> Instead, any update requires the creation of a new instance or infrastructure. The old instance is terminated after the new one is successfully deployed. Changes happen by replacing the infrastructure entirely.</p></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Configuration Drift</strong>
</div>
<div data-empty="true" style="text-align: left;">
<br>
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
Prone to <strong>configuration drift</strong>. Over time, as small changes are applied to systems manually or through different tools, the configuration of the system can deviate from its original state. This makes it harder to maintain consistency.
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Eliminates configuration drift</strong>. Every deployment starts fresh with a new environment, ensuring that the infrastructure always matches the desired state and behaves consistently.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Consistency</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
May lead to <strong>inconsistencies</strong> if manual changes are made, or if different versions of updates are applied across environments. This can result in unexpected behavior, particularly in environments that are long-lived or frequently updated.
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Highly consistent</strong> because each deployment uses a clean state. This ensures that each instance of the infrastructure are same, avoiding unexpected issues from differing configurations.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Downtime</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
Can be updated <strong>in-place</strong>, which often leads to shorter or no downtime. This is crucial for systems that require <strong>high availability&nbsp;</strong>and cannot afford to be redeployed.
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
May involve <strong>temporary downtime</strong> during the replacement process, depending on the strategy used (e.g., blue-green or rolling deployments). However, modern techniques like blue-green or canary deployments can mitigate this issue by seamlessly transitioning between old and new infrastructure.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Rollback Complexity</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>Rolling back</strong> changes can be complex because reverting to a previous configuration may not fully restore the infrastructure to its original state. In most cases, manual intervention may be required.
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>Rollback is simpler</strong>. Since new infrastructure is created for every change, rolling back is as easy as redeploying the previous, working version. This reduces the risk of failure when reverting to an earlier state.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Security</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Security patches</strong> are applied directly to running systems, which can leave them vulnerable to attack if patches are delayed or improperly applied. Manual patching introduces risks.
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
<strong>More secure</strong> because each update replaces the entire system with a fresh instance. This ensures that any vulnerabilities from previous configurations are completely removed, and patched versions are consistently applied.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Operational Overhead</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
Requires more <strong>maintenance</strong> and monitoring to ensure that updates are properly applied and systems remain secure over time. This can increase operational overhead, especially when managing large, complex environments.
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<p style="text-align: left;"><strong>Reduces operational overhead</strong> by standardizing updates and deployments. Since there’s no need to manage in-place updates, less effort is required to maintain consistency across environments.</p></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Resource Efficiency</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
More <strong>resource-efficient</strong> in some cases since updates are made to the existing resources without creating new ones. This can save costs and time, especially for updates that don’t require full system redeployment.
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
Requires the creation of <strong>new resources</strong> for every update, which can lead to <strong>increased costs and resource usage,</strong> particularly for environments that need frequent updates or scaling. However, automation tools can help manage this process more efficiently.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Use Cases</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
Suited for environments where <strong>rapid, in-place updates</strong> are needed without full redeployment (e.g., databases, development and testing environments, or legacy systems). It’s also practical for environments where costs need to be minimized by reusing existing infrastructure.
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
Best for environments where <strong>consistency, security, and reliability</strong> are critical, such as production environments, containerized applications, and microservices. Immutable infrastructure is ideal for organizations that prioritize automation, scaling, and continuous delivery.
</div></td>
</tr>
<tr style="overflow-wrap: break-word; width: auto;" width="auto">
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
<strong>Infrastructure Lifespan</strong>
</div></td>
<td style="overflow-wrap: break-word; width: auto;" width="auto">
<div style="text-align: left;">
Often associated with <strong>long-lived infrastructure</strong> where the same resources are maintained and updated over time. These systems may evolve as they stay active, leading to drift over time.
</div></td>
<td style="overflow-wrap: break-word; width: auto; vertical-align: top;" width="auto">
<div style="text-align: left;">
Typically associated with <strong>short-lived infrastructure</strong>. Resources are frequently replaced with newer versions, reducing the need for ongoing maintenance of the same system.
</div></td>
</tr>
</tbody>
</table>
</div>
<h3 style="text-align: left;">When to Choose Mutable Infrastructure</h3>
<p style="text-align: left;">While immutable infrastructure is often preferred in modern environments due to its consistency and reliability, there are still several scenarios where choosing mutable infrastructure is more practical and beneficial. Mutable infrastructure offers flexibility for certain use cases where in-place changes, cost-effectiveness, or maintaining long-lived systems are essential.</p>
<p style="text-align: left;">Here are some key situations where you should consider using mutable infrastructure:</p>
<ul>
<li style="text-align: left;"><strong>Dynamic or evolving environments -&nbsp;</strong>In scenarios where the infrastructure needs to <strong>frequently adapt to changes</strong>, such as in development or testing environments, mutable infrastructure is advantageous. Developers may need to quickly update configurations, modify code, or patch resources without spinning up new instances.</li>
<li style="text-align: left;"><strong>Cost-sensitive environments -&nbsp;</strong>Immutable infrastructure can increase operational costs, particularly in cloud environments where spinning up new instances for every update incurs additional expenses. For <strong>cost-sensitive environments</strong>, such as startups or organizations with tight budgets, mutable infrastructure can be more economical.</li>
<li style="text-align: left;"><a href="https://www.redhat.com/en/topics/cloud-native-apps/stateful-vs-stateless" rel="noopener noreferrer" target="_blank"><strong>Stateful applications&nbsp;</strong></a><strong>-&nbsp;</strong>Applications or services that maintain <strong>state</strong> (such as databases, file systems, or session-oriented services) benefit from mutable infrastructure. In these cases, tearing down and replacing infrastructure can lead to data loss or significant complexity in preserving state.</li>
<li style="text-align: left;"><strong>Legacy systems -&nbsp;</strong>Legacy systems often rely on mutable infrastructure due to their architecture and the fact that they weren’t designed with modern immutable practices in mind. Rewriting or migrating legacy applications to immutable infrastructure may be impractical, expensive, or risky, making mutable infrastructure the better choice.</li>
<li style="text-align: left;"><strong>Applications with infrequent updates -&nbsp;</strong>For environments or applications where updates are <strong>infrequent</strong> and the risk of configuration drift is low, mutable infrastructure can be a simple and effective solution. If the system doesn’t require constant adjustments or scaling, maintaining long-lived infrastructure may be sufficient.</li>
<li style="text-align: left;"><strong>Systems that require minimal downtime -&nbsp;</strong>Some critical systems cannot afford the downtime that might occur during the replacement of infrastructure, especially in high-availability environments. Mutable infrastructure allows for in-place updates, which can minimize or eliminate downtime altogether.</li>
<li style="text-align: left;"><strong>Systems with complex interdependencies -&nbsp;</strong>In environments where services or applications have <strong>complex interdependencies</strong>, managing immutable infrastructure might become difficult. When numerous components rely on each other, applying changes in place ensures those connections remain intact without needing to redeploy the entire infrastructure.</li>
</ul>
<h3 style="text-align: left;">When to Choose Immutable Infrastructure</h3>
<p style="text-align: left;">Immutable infrastructure has become a popular approach in today's IT world, especially in cloud-native and DevOps environments. It helps prevent configuration drift and guarantees consistent, reliable deployments. However, it's not always the best fit for every situation. There are cases where choosing immutable infrastructure is highly advantageous, particularly when consistency, security, and scalability are crucial priorities.</p>
<p style="text-align: left;">Here are key situations where choosing immutable infrastructure is the better choice:</p>
<ul>
<li style="text-align: left;"><strong>Production environments -&nbsp;</strong>Immutable infrastructure works exceptionally well in <strong>production environments</strong> where stability and reliability are key. By avoiding in-place changes, it keeps the production environment consistent and minimizes the risk of unexpected errors from manual updates or configuration drift. This makes it a solid choice when maintaining a reliable system is essential.</li>
<li style="text-align: left;"><strong>Security-conscious environments -&nbsp;</strong>In environments where <strong>security</strong> is a top priority, immutable infrastructure is a more secure option. Since no manual changes are applied after the infrastructure is deployed, there’s less risk of introducing vulnerabilities through untracked or insecure changes.</li>
<li style="text-align: left;"><strong>Microservices architectures -&nbsp;</strong><a href="https://microservices.io/" rel="noopener noreferrer" target="_blank"><strong>Microservices architectures</strong></a><strong>&nbsp;</strong>are built to be modular, making it easy to replace individual components. In these setups, immutable infrastructure plays a key role by ensuring each service is deployed consistently and independently, helping to avoid the risk of misconfigurations. This approach enhances reliability across the system.&nbsp;</li>
<li style="text-align: left;"><a href="https://dzone.com/articles/what-is-ci-cd"><strong>CI/CD</strong></a><strong> pipelines</strong><strong>&nbsp;and automation -&nbsp;</strong>Continuous Integration and Continuous Delivery (CI/CD) pipelines thrive on <strong>consistency and automation</strong>. Immutable infrastructure complements <a href="https://dzone.com/articles/how-to-build-an-effective-cicd-pipeline">CI/CD pipelines</a> by ensuring that every deployment is identical and repeatable, reducing the chances of failed builds or broken environments.</li>
<li style="text-align: left;"><strong>Disaster recovery and rollbacks -&nbsp;</strong>Immutable infrastructure simplifies <strong>disaster recovery</strong> and rollbacks. Since infrastructure is not modified after deployment, rolling back to a previous version is as simple as redeploying the last known working configuration. This reduces downtime and makes recovery faster and more reliable.</li>
<li style="text-align: left;"><strong>Scalability and&nbsp;</strong><a href="https://dzone.com/articles/microservices-architecture-introduction-to-auto-sc"><strong>auto-scaling</strong></a><strong>&nbsp;-&nbsp;</strong>In environments where <strong>scalability</strong> is a key requirement, immutable infrastructure supports automatic scaling by creating new instances as needed, rather than modifying existing ones. This is particularly useful for cloud-native applications or containerized environments where dynamic scaling is a common requirement.</li>
<li style="text-align: left;"><strong>Blue-green or canary deployments -&nbsp;</strong><a href="https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment#:~:text=Blue%20green%20deployment%20is%20an,which%20are%20running%20in%20production." rel="noopener noreferrer" target="_blank"><strong>Blue-green</strong></a> and <a href="https://cloud.google.com/deploy/docs/deployment-strategies/canary" rel="noopener noreferrer" target="_blank"><strong>canary</strong></a> deployment strategies are ideal candidates for immutable infrastructure. These deployment methods rely on running two environments simultaneously (blue and green), where the new version is tested before it fully replaces the old one.</li>
<li style="text-align: left;"><strong>Cloud-native and containerized applications -&nbsp;</strong><a href="https://aws.amazon.com/what-is/cloud-native/#:~:text=Cloud%20native%20is%20the%20software,quickly%20to%20meet%20customer%20demands." rel="noopener noreferrer" target="_blank"><strong>Cloud-native</strong></a> and <a href="https://cloud.google.com/discover/what-are-containerized-applications?hl=en" rel="noopener noreferrer" target="_blank"><strong>containerized applications</strong></a> naturally align with immutable infrastructure because they are designed to be stateless, scalable, and disposable. Infrastructure as Code (IaC) tools like Terraform, combined with container orchestration platforms like Kubernetes, benefit greatly from immutable practices.</li>
<li style="text-align: left;"><strong>High-availability systems -&nbsp;</strong><strong>High-availability systems</strong> that cannot tolerate downtime can benefit from immutable infrastructure. With rolling or blue-green deployments, updates are applied seamlessly, ensuring that there is no disruption to the end user.</li>
</ul>
<h2 style="text-align: left;">Hybrid Approaches: Combining Mutable and Immutable Infrastructure</h2>
<p style="text-align: left;">While immutable infrastructure offers reliability and consistency, and mutable infrastructure provides flexibility and state retention, many organizations can benefit from a <strong>hybrid approach</strong>. By combining the best of both models, you can build a more flexible infrastructure that adapts to the specific needs of different components in your environment. This balanced approach allows you to address varying requirements more effectively.</p>
<p style="text-align: left;">A hybrid approach typically involves using <strong>immutable infrastructure</strong> for stateless services, where consistency and repeatability are essential, and <strong>mutable infrastructure</strong> for stateful services or legacy systems, where preserving data and flexibility is more important. <a href="https://www.terraform.io/" rel="noopener noreferrer" target="_blank">Terraform</a>, as a powerful <a href="https://dzone.com/refcardz/getting-started-with-iac">Infrastructure as Code (IaC)</a> tool, can manage both models simultaneously, giving you the flexibility to implement a hybrid approach effectively.</p>
<h3><strong>Use Immutable Infrastructure for Stateless Components</strong></h3>
<p><strong>Stateless services&nbsp;</strong>and applications that don’t rely on maintaining internal state across sessions are ideal for immutable infrastructure. These services can be replaced or scaled without the need for in-place updates.&nbsp;</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: With Terraform, you can manage web server deployments behind a load balancer seamlessly. Each time the application is updated, new instances are deployed while the old ones are removed. This ensures that the web servers are always running the latest version of the application, without any risk of configuration drift.</li>
</ul>
<h3><strong>Use Mutable Infrastructure for Stateful Components </strong></h3>
<p>Stateful components, such as <strong>databases</strong>, file systems, or applications that retain session data, require mutable infrastructure to preserve the data across updates. Replacing these components in an immutable model would involve complex data migration and could risk data loss.</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: Manage a relational database like <a href="https://www.postgresql.org/" rel="noopener noreferrer" target="_blank">PostgreSQL</a> using Terraform, where you need to update storage capacity or apply security patches without replacing the database instance. This ensures that the data remains intact while the infrastructure is modified.</li>
</ul>
<h3><strong>Automate Infrastructure Management With Terraform </strong></h3>
<p>Terraform’s ability to define infrastructure as code allows you to automate both mutable and immutable deployments. With a hybrid approach, you can use Terraform to manage both types of infrastructure side by side, ensuring consistency where needed and flexibility where required.</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: Use Terraform to define both immutable and mutable resources in a single deployment plan. For example, use immutable infrastructure for auto-scaling application servers, while managing stateful databases with mutable infrastructure for in-place updates.</li>
</ul>
<h3><strong>Implement Hybrid Scaling Strategies </strong></h3>
<p>In environments with both stateless and stateful services, <strong>scaling strategies&nbsp;</strong>can benefit from a hybrid approach. Stateless services can be scaled horizontally using immutable infrastructure, while stateful services may require vertical scaling or more complex approaches.</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: Use Terraform to manage auto-scaling groups for stateless web servers while adjusting database resources (such as memory or CPU) for stateful services through mutable infrastructure. This ensures that both types of services can scale based on their unique needs.</li>
</ul>
<h3><strong>Legacy System Modernization</strong></h3>
<p>Many organizations have <strong>legacy systems&nbsp;</strong>that are critical to their operations but are not easily moved to an immutable infrastructure model. In these cases, a hybrid approach allows organizations to maintain these legacy systems with mutable infrastructure while using immutable infrastructure for newer, cloud-native components.</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: Use Terraform to manage infrastructure for both legacy and modern applications. The legacy system (e.g., an on-premises ERP) can be maintained with mutable infrastructure, while cloud-native microservices are deployed with immutable infrastructure in the cloud.</li>
</ul>
<h3><strong>Simplifying Disaster Recovery With Hybrid Approaches</strong></h3>
<p>A hybrid approach can simplify <strong>disaster recovery&nbsp;</strong>by leveraging the benefits of both models. Immutable infrastructure can be used for services that need quick rollbacks, while mutable infrastructure can handle systems that need to retain their state after recovery.</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: In a hybrid cloud environment managed by Terraform, stateless services (like a front-end application) can be redeployed quickly with immutable infrastructure, while stateful services (like a database) can be restored from backups using mutable infrastructure.</li>
</ul>
<h3><strong>Security and Compliance Considerations</strong></h3>
<p>Security-sensitive applications benefit from immutable infrastructure due to the reduction in configuration drift and manual changes. However, some services, especially those involving sensitive data (like customer databases), may require mutable infrastructure for <strong>security patching&nbsp;</strong>and retention of critical state information. &nbsp;Also it is important to note that the evidence is updated when immutable infrastructure are used.&nbsp;</p>
<ul style="text-align: left;">
<li style="text-align: left;"><strong>Example</strong>: Use immutable infrastructure for API gateways and front-end services to ensure they are always deployed with the latest security patches. Simultaneously, manage the back-end databases using mutable infrastructure, allowing for in-place security patches without affecting stored data.</li>
<li style="text-align: left;"><strong>Example</strong>: Terraform can be used to manage testing environments with immutable infrastructure, ensuring that each test is performed on a fresh, consistent environment. Meanwhile, long-lived production databases are managed with mutable infrastructure, allowing for updates and scaling without disruption.</li>
</ul>
<h2 style="text-align: left;">Conclusion</h2>
<p style="text-align: left;">A hybrid approach to infrastructure combines the best of both mutable and immutable models, offering flexibility for stateful and legacy systems while ensuring consistency and scalability for stateless services. By using Terraform to manage this blend, organizations can optimize their infrastructure for dynamic needs, balancing reliability, cost-efficiency, and operational flexibility. This approach allows for tailored strategies that meet the unique demands of various applications and services.</p></div>
</div>
<div id="bottom-bumper-container"></div>
<div class="article-tag-pill-container">
<span class="article-tag-pill">Disaster recovery</span>
<span class="article-tag-pill">Infrastructure</span>
<span class="article-tag-pill">Cloud</span>
<span class="article-tag-pill">systems</span>
<span class="article-tag-pill">Terraform (software)</span>
</div>
<div class="attribution">
<p>Opinions expressed by DZone contributors are their own.</p>
</div>
</div>
</article>
</div>
<div class="trending-separator goto"></div>
<aside class="trending goto" aria-labelledby="related-mobile-heading">
<h2 id="related-mobile-heading">Related</h2>
<ul>
<li class="item">
<a href="/articles/cloud-automation-excellence-terraform-ansible-amp" class="goto-link related-link">Cloud Automation Excellence: Terraform, Ansible, and Nomad for Enterprise Architecture</a>
</li>
<li class="item">
<a href="/articles/unlock-the-power-of-terragrunts-hierarchy" class="goto-link related-link">Unlock the Power of Terragrunt’s Hierarchy</a>
</li>
<li class="item">
<a href="/articles/how-to-reduce-the-impact-of-a-cloud-outage" class="goto-link related-link">How To Reduce the Impact of a Cloud Outage</a>
</li>
<li class="item">
<a href="/articles/ai-cloud-infrastructure" class="goto-link related-link">Why Traditional Cloud Infrastructure Breaks AI Workloads in Production</a>
</li>
</ul>
</aside>
</div>
<div id="div-gpt-ad-1435246566686-11" class="ads-bottom-leaderboard dz2_article_bottom" data-gpt-slot="bottom"></div>
<div class="layout-card widget-top-border partner-resources-block" style="width:100%; margin-bottom: 1em;">
<div class="main-container">
<div class="featured-header">
<h2>
<span>Partner Resources</span>
</h2>
</div>
<div class="partner-resources-container">
<div id="div-gpt-ad-1435246566686-5" class="resource-block dz2_partner_resource_link" data-gpt-slot="partner" data-gpt-position="pr1"></div>
<div id="div-gpt-ad-1435246566686-6" class="resource-block dz2_partner_resource_link" data-gpt-slot="partner" data-gpt-position="pr2"></div>
<div id="div-gpt-ad-1435246566686-7" class="resource-block dz2_partner_resource_link" data-gpt-slot="partner" data-gpt-position="pr3"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bottom-sticky-ad-container">
<span class="bottom-sticky-ad-close" title="close"
x-on:click="$el.parentElement.classList.add('closed')">×</span>
<div id="div-gpt-ad-1635294790718-12" class="bottom-sticky-ad dz2_sticky_footer_leaderboard" data-gpt-slot="bottomStickyFooter"></div>
</div>
<div class="modal fade bd-example-modal-lg" id="modal-message" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header"></div>
<div class="modal-body"></div>
</div>
</div>
</div>
</div>
</div>
<div class="comments-overlay"></div>
<div id="comment-box">
<div class="comment-box-wrapper">
<div id="comment-input-editor"></div>
</div>
<div class="info hidden"></div>
<div class="comments-content" style="display: none;">
<div class="comment-header">
<hr />
<span class="icon-comment">
<span class="numOfComments"></span> Comments
</span>
</div>
<div class="comments"></div>
</div>
</div>
<script async>var articleTitle = 'Mutable vs. Immutable: Infrastructure Models in the Cloud Era';
var articleUrl = 'https://dzone.com/articles/infrastructure-models-in-the-cloud-era';
var retweetLink = document.querySelector('#tweet-link');
function retweet(event) {
event.preventDefault();
event.stopPropagation();
var twitter = 'https://twitter.com/intent/tweet';
var params = '?text=' + encodeURIComponent(articleTitle) + '&url=' + articleUrl + '&ref=dzone.com&via=DZoneInc';
var win = window.open(twitter + params, '_blank');
win.focus();
}
retweetLink.addEventListener('click', retweet);
function showStatusMessage(options) {
var modal = document.getElementById('modal-message');
if(modal) {
modal.classList.add(options.type);
var modalBody = modal.querySelector('.modal-content .modal-body');
var modalHeader = modal.querySelector('.modal-content .modal-header');
modalHeader.innerText = options.header ? options.header : '';
modalBody.innerText = options.body ? options.body : '';
$(modal).modal('show');
$(modal).on('hidden.bs.modal', function () {
modal.classList.remove(options.type);
});
}
}
function showConfirmMessage(options) {
var modal = document.getElementById('modal-message');
if(modal) {
modal.classList.add(options.type);
var modalBody = modal.querySelector('.modal-content .modal-body');
var modalHeader = modal.querySelector('.modal-content .modal-header');
modalHeader.innerText = options.header ? options.header : '';
modalBody.innerText = options.body ? options.body : '';
if (options.textarea) {
var textareaDiv = document.createElement('div');
var textareaLabel = document.createElement('label');
textareaLabel.setAttribute('for', 'modal-textarea');
textareaLabel.innerText = options.textarea.label;
var textarea = document.createElement('textarea');
textarea.id = 'modal-textarea';
textarea.placeholder = (options.textarea.placeholder || '');
textarea.setAttribute('rows', (options.textarea.rows || 3));
textarea.classList.add('form-control', 'not-resizable');
if (options.textarea.maxlength) {
textarea.maxLength = options.textarea.maxlength;
}
textareaDiv.appendChild(textareaLabel);
textareaDiv.appendChild(textarea);
modalBody.appendChild(textareaDiv);
}
var btnContainer = document.createElement('div');
btnContainer.classList.add('btn-container');
var noBtn = document.createElement('button');
noBtn.innerText = options.noBtnText ? options.noBtnText : 'No';
noBtn.classList.add('no-btn');
var yesBtn = document.createElement('button');
yesBtn.innerText = options.yesBtnText ? options.yesBtnText : 'Yes';
yesBtn.classList.add('yes-btn');
btnContainer.appendChild(noBtn);
btnContainer.appendChild(yesBtn);
modalBody.appendChild(btnContainer);
$(modal).modal('show');
$(noBtn).one('click', function() {
$(modal).modal('hide');
if(options.noCallback) {
$(modal).one('hidden.bs.modal', function () {
options.noCallback();
});
}
});
$(yesBtn).one('click', function() {
$(modal).modal('hide');
if(options.yesCallback) {
$(modal).one('hidden.bs.modal', function () {
options.yesCallback();
});
}
});
$(modal).on('hidden.bs.modal', function () {
modal.classList.remove(options.type);
});
}
}
function getSuspensionBody() {
return 'We regret to inform you that your DZone account has been suspended for violating our Guidelines. ' +
'Please reach out to editors@dzone.com if you would like additional information.';
}</script>
<style>.engagement-overlay {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
background: rgb(0, 0, 0, 0.5);
z-index: 10000;
}
.engagement-modal {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 10;
width: 100%;
height: 100%;
}
.engagement-modal .inner {
background-color: white;
border-radius: 0.5em;
margin: auto;
border: 1px solid #cccccc;
}
.engagement-modal .header {
padding: 20px 50px 10px 30px;
position: relative;
}
.engagement-modal .title {
font-size: 20px;
font-weight: bold;
color: #333333;
}
.engagement-modal .title:hover {
text-decoration: none;
}
.engagement-modal .close {
font-size: 18px;
position: absolute;
top: 18px;
right: 20px;
width: 32px;
height: 32px;
background: none;
border: none;
opacity: 0.8;
font-weight: bold;
text-shadow: 0 1px 0 #fff;
}
.engagement-modal .close:hover {
background-color: rgba(146, 148, 151, 0.2);
color: #000;
border-radius: 50%;
}
.engagement-modal .close:after {
content: '\2715';
}
.engagement-modal .content {
padding: 0 30px 20px;
width: min(450px, 90vw);
height: min(450px, 90vw);
scrollbar-width: thin;
overflow: auto;
overscroll-behavior: contain;
}
.engagement-modal .loading-screen,
.engagement-modal .content .center-screen {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-size: 18px;
}
.engagement-modal .content .center-screen a {
color: var(--acc-ffffff-blue-1);
font-weight: bold;
}
.engagement-modal .loading-screen i {
font-size: 24px;
}
.engagement-modal .media-left,
.engagement-modal .media-right {
display: table-cell;
vertical-align: top;
}
.engagement-modal .media-left {
padding-right: 10px;
}
.engagement-modal .media-right {
padding-left: 10px;
}
.engagement-modal .media a {
color: black;
font-size: 16px;
}
.engagement-modal .avatar {
border-radius: 50%;
}
.engagement-modal .footer {
margin: 20px 0 0;
display: flex;
justify-content: center;
align-items: center;
background-color: unset !important;
border-top: none !important;
}
.engagement-modal .footer .btn {
border: 1px solid transparent;
}
.engagement-modal .footer .btn-primary {
color: #fff;
border-color: #2e6da4;
}
.engagement-modal .footer button {
background-color: var(--acc-ffffff-blue-2);
padding: 6px 12px;
border-radius: 4px;
}
.engagement-modal .footer button:hover {
filter: brightness(1.2);
}
@keyframes anim-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}
}
.engagement-modal .anim-spin {
display: inline-block;
animation: anim-spin 2s infinite linear;
}</style>
<script>document.addEventListener('alpine:init', () => {
Alpine.data('engagementModal', (nodeId) => ({
nodeId: null,
init() {
this.nodeId = nodeId;
},
open() {
this.updateStore();
this.$store.article.engagement.open = true;
if (this.$store.article.engagement.page === 1 && !this.$store.article.engagement.unauthorized) {
this.$store.article.engagement.initializing = true;
this.fetchEngagements();
}
},
close() {
if (this.$store.article.engagement.open) {
this.$store.article.engagement.open = false;
}
},
updateStore() {
if (this.nodeId !== this.$store.article.id) {
this.$store.article.engagement.reset();
this.$store.article.id = this.nodeId;
}
},
fetchEngagements() {
if (this.$store.article.engagement.loading || !this.$store.article.engagement.additional) {
return;
}
this.$store.article.engagement.loading = true;
this.$store.global.getFromService('/services/nodes/' + this.$store.article.id + '/engagements?page=' + this.$store.article.engagement.page)
.then(res => {
res.json().then(data => {
for (let user of data.engagements) {
this.$store.article.engagement.users.push(user);
}
this.$store.article.engagement.additional = data.additional;
this.$store.article.engagement.page++;
});
})
.catch(err => {
err.json().then(data => {
if (data.error?.code === 4011) {
this.$store.article.engagement.unauthorized = true;
} else {
this.$store.modal_engagement_error.open();
}
});
})
.finally(() => {
// Allow the loader to gracefully exit
setTimeout(() => {
this.$store.article.engagement.loading = false;
this.$store.article.engagement.initializing = false;
}, 200);
});
},
formatJobData(user) {
if (user.profile.jobTitle && user.profile.companyName) {
return user.profile.jobTitle + ', ' + user.profile.companyName;
}
if (user.profile.jobTitle) {
return user.profile.jobTitle;
}
if (user.profile.companyName) {
return user.profile.companyName;
}
return null;
},
isDataUnavailable() {
return !this.$store.article.engagement.initializing && !this.$store.article.engagement.users.length;
},
isFooterShowing() {
return !this.$store.article.engagement.initializing
&& this.$store.article.engagement.additional
&& this.$store.article.engagement.page > 1;
}
}));
});
</script>
<div class="alpine-overlay" x-cloak x-show="$store.modal_engagement_error._open">
<div id="modal_engagement_error"
class="alpine-modal"
role="dialog"
tabindex="-1"
x-show="$store.modal_engagement_error._open"
x-on:click.self="$store.modal_engagement_error.dismissible && $store.modal_engagement_error.close()"
x-cloak
x-transition
>
<div class="dz-style modal-inner centered relative">
<button x-show="$store.modal_engagement_error.closeable"
class="btn-close"
x-on:click="$store.modal_engagement_error.close()"
aria-label="Close">
</button>
<div x-show="$store.modal_engagement_error.title" class="modal-header p-sm mt-sm mb-md">
<div class="title " x-text="$store.modal_engagement_error.title"></div>
</div>
<div class="modal-content py-md px-lg" x-bind:class="{ 'has-top-border': $store.modal_engagement_error.title }">
<p x-show="$store.modal_engagement_error.bodyText" class="my-none" x-text="$store.modal_engagement_error.bodyText"></p>
<p>The likes didn't load as expected. Please refresh the page and try again.</p>
</div>
<div x-show="$store.modal_engagement_error.options.length" class="modal-footer p-sm">
<template x-for="option in $store.modal_engagement_error.options">
<button x-show="option.canDisplay" x-text="option.text"
type="button"
x-bind:id="'button_modal_engagement_error_' + option.index"
x-bind:class="option.classList"
x-on:click="option.onClick"
x-bind:disabled="option.isDisabled"
></button>
</template>
</div>
</div>
</div>
</div>
<script>
document.addEventListener("alpine:init", () => {
Alpine.store("modal_engagement_error", {
_open: false,
title: "Oops! Something Went Wrong",
bodyText: null,
options: [{"action":"dismiss","text":"Close"}],
closeable: true,
dismissible: true,
open(data) {
if (data) {
if (data.title) {
this.title = data.title;
}
if (data.bodyText) {
this.bodyText = data.bodyText;
}
if (data.options) {
this.options = data.options;
}
if (data.dismissAfterMs) {
setTimeout(() => this._open = false, data.dismissAfterMs);
}
}
this.updateOptions();
this._open = true;
},
close() {
// Manually click the buttons in which should run on dismiss.
// This is to keep the context. Calling this[option.action]() will not work.
for (let option of this.options) {
if (option.runOnDismiss) {
const element = document.querySelector('#button_modal_engagement_error_' + option.index);
element.click();
}
}
this._open = false;
},
updateOptions() {
const btnStyle = this.options.length === 2 ? ' btn-default' : '';
this.options = this.options.map((o, idx) => ({
...o,
index: idx,
classList: o.classList ? o.classList : (idx === 0 ? "btn btn-primary hov-brighten" : "btn hov-underline" + btnStyle),
onClick: function() {
if (o.action !== "dismiss") {
this[o.action]();
}
this.$store["modal_engagement_error"].close();
},
isDisabled: function() {
return Object.hasOwn(o, 'disabled') && this[o.disabled]();
},
canDisplay: function() {
return !Object.hasOwn(o, 'condition') || this[o.condition]();
}
}));
},
init() {
this.updateOptions();
}
});
});
</script>
<link rel="stylesheet" media="all" href="https://dz2cdn1.dzone.com/themes/dz20/ftl/footer/styles.css">
<div id="ftl-footer">
<div class="container-fluid footerOuter" style="padding-bottom: 90px;">
<div class="row">
<div class="col-md-12">
<div class="container">
<div class="row footer">
<div class="col-md-12 footerWidget">
<div class="row footerContainer footer">
<div class="left col-xs-12 col-sm-7">
<div class="col-xs-12 social-media-icons footer-mobile">
<ul class="icons-only">
<li class="rss-icon" id="rss-footer-1">
<a href="/pages/feeds" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" class="w-4 h-4 mt-1.75 fill-current" aria-label="Follow our RSS feeds">
<title>RSS</title>
<path d="M19.199 24C19.199 13.467 10.533 4.8 0 4.8V0c13.165 0 24 10.835 24 24h-4.801zM3.291 17.415c1.814 0 3.293 1.479 3.293 3.295 0 1.813-1.485 3.29-3.301 3.29C1.47 24 0 22.526 0 20.71s1.475-3.294 3.291-3.295zM15.909 24h-4.665c0-6.169-5.075-11.245-11.244-11.245V8.09c8.727 0 15.909 7.184 15.909 15.91z"></path>
</svg>
</a>
</li>
<li class="twitter-icon">
<a href="https://twitter.com/DZoneInc" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" aria-label="Follow us on X">
<title>X</title>
<path d="M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z"></path>
</svg>
</a>
</li>
<li class="facebook-icon">
<a href="https://www.facebook.com/DZoneInc" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" aria-label="Follow us on Facebook">
<title>Facebook</title>
<path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"></path>
</svg>
</a>
</li>
<li class="linkedin-icon">
<a href="https://www.linkedin.com/company/dzone/" target="_blank"
rel="noreferrer noopener">
<svg viewBox="0 0 24 25" fill="none" aria-label="Follow us on LinkedIn">
<path d="M6.20062 21.2143H1.84688V7.194H6.20062V21.2143ZM4.02141 5.2815C2.62922 5.2815 1.5 4.12838 1.5 2.73619C1.5 2.06747 1.76565 1.42614 2.2385 0.953285C2.71136 0.48043 3.35269 0.214783 4.02141 0.214783C4.69012 0.214783 5.33145 0.48043 5.80431 0.953285C6.27716 1.42614 6.54281 2.06747 6.54281 2.73619C6.54281 4.12838 5.413 5.2815 4.02141 5.2815ZM22.4953 21.2143H18.1509V14.3893C18.1509 12.7628 18.1181 10.6768 15.8873 10.6768C13.6237 10.6768 13.2769 12.444 13.2769 14.2721V21.2143H8.92781V7.194H13.1034V9.1065H13.1644C13.7456 8.00494 15.1655 6.84244 17.2838 6.84244C21.69 6.84244 22.5 9.744 22.5 13.5128V21.2143H22.4953Z" fill="currentColor"></path>
</svg>
</a>
</li>
</ul>
</div>
<div class="top-section col-xs-12">
<div class="col-xs-12 col-sm-6">
<p class="section-header">ABOUT US</p>
<ul class="link-group">
<li><a href="/pages/about" rel="noreferrer noopener">About DZone</a></li>
<li><a href="/cdn-cgi/l/email-protection#394a4c4949564b4d795d4356575c175a5654" rel="noreferrer noopener">Support and feedback</a></li>
<li><a href="/pages/dzone-community-research">Community research</a></li>
</ul>
</div>
<div class="col-xs-12 col-sm-6">
<p class="section-header">ADVERTISE</p>
<ul class="link-group">
<li><a href="https://advertise.dzone.com" target="_blank" rel="noreferrer noopener">Advertise with DZone</a></li>
</ul>
</div>
</div>
<div class="bottom-section col-xs-12">
<div class="col-xs-12 col-sm-6">
<p class="section-header">CONTRIBUTE ON DZONE</p>
<ul class="bottom-top-list link-group">
<li><a href="/articles/dzones-article-submission-guidelines">Article Submission Guidelines</a></li>
<li><a href="/pages/contribute" rel="noreferrer noopener">Become a Contributor</a></li>
<li><a href="/pages/core" rel="noreferrer noopener">Core Program</a></li>
<li><a href="/writers-zone" rel="noreferrer noopener">Visit the Writers' Zone</a></li>
</ul>
<p class="section-header">LEGAL</p>
<ul class="link-group">
<li><a href="https://technologyadvice.com/terms-conditions/" target="_blank" rel="noreferrer noopener">Terms of Service</a></li>
<li><a href="https://technologyadvice.com/privacy-policy/" target="_blank" rel="noreferrer noopener">Privacy Policy</a></li>
</ul>
</div>
<div class="col-xs-12 col-sm-6">
<p class="section-header">CONTACT US</p>
<ul class="link-group">
<li>3343 Perimeter Hill Drive</li>
<li>Suite 215</li>
<li>Nashville, TN 37211</li>
<li><a href="/cdn-cgi/l/email-protection#6f1c1a1f1f001d1b2f0b1500010a410c0002" rel="noreferrer noopener"><span class="__cf_email__" data-cfemail="6b181e1b1b04191f2b0f1104050e45080406">[email&#160;protected]</span></a></li>
</ul>
</div>
</div>
</div>
<div class="right col-xs-12 col-sm-5">
<p class="connect-text">Let's be friends:</p>
<div class="col-xs-12 social-media-icons footer-wide">
<ul class="icons-only">
<li class="rss-icon" id="rss-footer-1">
<a href="/pages/feeds" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" aria-label="Follow our RSS feeds">
<title>RSS</title>
<path d="M19.199 24C19.199 13.467 10.533 4.8 0 4.8V0c13.165 0 24 10.835 24 24h-4.801zM3.291 17.415c1.814 0 3.293 1.479 3.293 3.295 0 1.813-1.485 3.29-3.301 3.29C1.47 24 0 22.526 0 20.71s1.475-3.294 3.291-3.295zM15.909 24h-4.665c0-6.169-5.075-11.245-11.244-11.245V8.09c8.727 0 15.909 7.184 15.909 15.91z"></path>
</svg>
</a>
</li>
<li class="twitter-icon">
<a href="https://twitter.com/DZoneInc" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" aria-label="Follow us on X">
<title>X</title>
<path d="M14.234 10.162 22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299-.929-1.329L3.076 1.56h3.182l5.965 8.532.929 1.329 7.754 11.09h-3.182z"></path>
</svg>
</a>
</li>
<li class="facebook-icon">
<a href="https://www.facebook.com/DZoneInc" target="_blank" rel="noreferrer noopener">
<svg role="img" viewBox="0 0 24 24" aria-label="Follow us on Facebook">
<title>Facebook</title>
<path d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"></path>
</svg>
</a>
</li>
<li class="linkedin-icon">
<a href="https://www.linkedin.com/company/dzone/" target="_blank"
rel="noreferrer noopener">
<svg viewBox="0 0 24 25" fill="none" aria-label="Follow us on LinkedIn">
<path d="M6.20062 21.2143H1.84688V7.194H6.20062V21.2143ZM4.02141 5.2815C2.62922 5.2815 1.5 4.12838 1.5 2.73619C1.5 2.06747 1.76565 1.42614 2.2385 0.953285C2.71136 0.48043 3.35269 0.214783 4.02141 0.214783C4.69012 0.214783 5.33145 0.48043 5.80431 0.953285C6.27716 1.42614 6.54281 2.06747 6.54281 2.73619C6.54281 4.12838 5.413 5.2815 4.02141 5.2815ZM22.4953 21.2143H18.1509V14.3893C18.1509 12.7628 18.1181 10.6768 15.8873 10.6768C13.6237 10.6768 13.2769 12.444 13.2769 14.2721V21.2143H8.92781V7.194H13.1034V9.1065H13.1644C13.7456 8.00494 15.1655 6.84244 17.2838 6.84244C21.69 6.84244 22.5 9.744 22.5 13.5128V21.2143H22.4953Z" fill="currentColor"></path>
</svg>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>
const articleId = 3500368;
const likes = 4;
const assetDomain = 'https://dz2cdn1.dzone.com';
const codemirrorVars = {
modeURI: 'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/mode/',
requiredScripts: [
'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/lib/codemirror.js',
'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/addon/mode/overlay.js',
'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/addon/mode/multiplex.js',
'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/mode/meta.js'
]
};
const gptTags = {
'zone': 'Cloud Architecture',
'topicTag': 'Disaster recovery,Infrastructure,cloud,systems,terraform',
'company': '',
'siteSection': 'Zones',
'articleCategory': 'analysis',
'nodeID': '3500368',
'authorID': '4658384,5219734',
'publishYear': '2024',
'publishMonth': '10',
'jobRole': '',
'companySize': '',
'env': 'prod'
};
const minCommentChar = 10;
</script>
<script async>const width = window.innerWidth;
const metadata = {
'top': {
'position': 'top',
'slot': 'dz2_article_billboard_new',
},
'sponsorLogo': {
'position': 'zoneHomepage',
'slot': 'dz2_homepage_sponsor_logo',
'refreshable': false
},
'sidebar1': {
'position': 'sidebar',
'slot': 'dz2_article_halfpage_new',
'minWidthToShow': 1024
},
'topBumper': {
'position': 'top',
'slot': 'dz2_bumper_text_ad',
'minWidthToShow': 1024
},
'bottomBumper': {
'position': 'bottom',
'slot': 'dz2_bumper_text_ad',
'minWidthToShow': 1024
},
'bottom': {
'position': 'bottom',
'slot': 'dz2_article_bottom',
},
'bottomStickyFooter': {
'position': 'sticky',
'slot': 'dz2_sticky_footer_leaderboard',
},
'partner': {
'slot': 'dz2_partner_resource_link',
},
'branded': {
'slot': 'dz2_branded_content',
'refreshable': false
},
'topicBillboard': {
'position': ['top', 'zoneHomepage'],
'slot': 'dz2_topic_billboard',
},
'listPageSidebar': {
'position': 'sidebar',
'slot': 'dz2_list_page_sidebar',
'minWidthToShow': 1024
},
'topListPageLeaderboard2': {
'position': ['top', 'zoneList'],
'slot': 'dz2_list_page_leaderboard_2',
},
'bottomListPageLeaderboard2': {
'position': ['bottom', 'zoneList'],
'slot': 'dz2_list_page_leaderboard_2',
},
'homepageLeaderboard': {
'position': 'top',
'slot': 'dz2_homepage_leaderboard',
},
'homepageLeaderboard2': {
'position': 'bottom',
'slot': 'dz2_homepage_leaderboard_2',
},
'skybox': {
'position': 'above nav',
'slot': 'dz_skybox',
'refreshable': false
},
'inline': {
'position': 'inline',
'slot': 'dz2_inline-article-display',
}
};
var campaign = new URLSearchParams(window.location.search).get("adTargeting_campaign");
window.googletag = window.googletag || { cmd: [] };
if (campaign) {
window.googletag.cmd.push(function() {
window.googletag.setConfig({ targeting: { campaign }});
});
}
let lastHeader = null;
const topContainer = document.querySelector('#top-bumper-container');
const bottomContainer = document.querySelector('#bottom-bumper-container');
function GAM_getPersistentValue(key) {
const stored = JSON.parse(localStorage.getItem(key));
if (!stored) {
return null;
}
const { value, expiration } = stored;
if (expiration && Date.now() >= expiration) {
localStorage.removeItem(key);
return null;
}
return value;
}
function GAM_setPersistentValue(key, value, expiration) {
// 5 minutes from now
if (!expiration) {
expiration = Date.now() + 300000;
}
const storedValue = JSON.stringify({
value: value,
expiration: expiration
});
localStorage.setItem(key, storedValue);
return value;
}
function GAM_synchronousRequest(params) {
const xhr = new XMLHttpRequest();
xhr.open('GET', params.url, false);
xhr.setRequestHeader("Content-Type", "application/json");
if (typeof params.auth_header !== "undefined") {
xhr.setRequestHeader("Authorization", params.auth_header);
}
xhr.send(null);
if (xhr.status === 200) {
return xhr.responseText;
} else {
throw new Error('Request failed: ' + xhr.statusText);
}
}
function GAM_fetch_data(params) {
let stored_data = GAM_getPersistentValue(params.storage_key);
if (stored_data === null) {
try {
const response = GAM_synchronousRequest(params);
const data = JSON.parse(response);
// Store and expire after 30 minutes
return GAM_setPersistentValue(params.storage_key, data, Date.now() + 1800000);
} catch (error) {
console.error('Could not get ' + params.storage_key + ' data: ' + error);
return null;
}
} else {
return stored_data;
}
}
function GAM_setUpSixSenseTargeting() {
let meData = GAM_fetch_data({
url: "https://link.technologyadvice.com/_me",
storage_key: "ta_me_data"
});
let sixSenseData = GAM_fetch_data({
url: "https://epsilon.6sense.com/v3/company/details",
auth_header: "Token d20a1b0e892442270cbc4cb6801c0160d28af04c",
storage_key: "ta_6s_data"
});
function meDataIncludes(i) {
return meData.tags.includes(i);
}
if (typeof meData !== "undefined" && meData !== null) {
window.googletag.pubads().setTargeting("visitor_id", meData.vid);
window.googletag.pubads().setTargeting("user_agent", meData.user_agent);
var tags_mapping = {
"is_datacenter": ["site.is-datacenter"],
"is_suspected_bot": ["site.suspected-bad-bot", "site.bad-bot"],
"is_ta_user": ["site.is-ta-user"],
"is_crawler": ["site.user-agent-blocked"],
"is_ad_blocked": ["site.is-ad-blocked"],
};
for (var key in tags_mapping) {
if (tags_mapping[key].some(meDataIncludes)) {
window.googletag.pubads().setTargeting(key, 'true');
}
}
}
if (typeof sixSenseData !== "undefined" && sixSenseData !== null) {
var segment_ids = [];
if (sixSenseData.segments && sixSenseData.segments.ids && sixSenseData.segments.ids.length) {
sixSenseData.segments.ids.forEach(function (v) {
segment_ids.push(v.toString());
});
}
if (typeof segment_ids !== "undefined" && segment_ids.length > 0) {
window.googletag.pubads().setTargeting("segment_ids_6si", segment_ids);
}
}
}
if (width >= 1024 && (topContainer || bottomContainer)) {
// Dynamically create bumper ad slots for non-mobile devices.
// Prevents ugly dividers being rendered on empty ad slots (mobile)
const topBumper = document.createElement('div');
topBumper.id = 'div-gpt-ad-1435246566686-3';
topBumper.classList.add('article-bumper', 'article-bumper-top', 'dz2_bumper_text_ad');
topBumper.setAttribute('data-gpt-slot', 'topBumper');
topContainer.appendChild(topBumper);
const bottomBumper = document.createElement('div');
bottomBumper.id = 'div-gpt-ad-1435246566686-4';
bottomBumper.classList.add('article-bumper', 'article-bumper-bottom', 'dz2_bumper_text_ad');
bottomBumper.setAttribute('data-gpt-slot', 'bottomBumper');
bottomContainer.appendChild(bottomBumper);
}
if (gptTags.zone) {
gptTags.zone = gptTags.zone.replaceAll(/[\s/]/g, '_')
.replaceAll(/[^a-zA-Z0-9_]/g, '')
.toLowerCase();
}
makeAds();
function handleSkybox() {
const skybox = document.querySelector('div.skybox');
if (skybox) {
document.body.classList.add('skybox-auto-collapse');
// observe classlist changes for offsetting sticky ads
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
let offset = 0;
if (!document.body.classList.contains('skybox-closed') && (
document.body.classList.contains('ccad-skybox-manualcollapse')
|| document.body.classList.contains('ccad-skybox-manualexpand')
)) {
offset = skybox.getBoundingClientRect().height;
}
let eligibleAds = [
{ element: document.querySelector('.content-right-images'), offset: 108 },
{ element: document.querySelector('.trending-sidebar'), offset: 88 },
{ element: document.querySelector('.trending'), offset: 88 }
];
for (let ad of eligibleAds) {
if (ad.element) {
ad.element.style.top = (ad.offset + offset) + 'px';
}
}
}
});
});
observer.observe(document.body, { attributes: true });
}
}
function isHeaderEligible(header) {
const range = document.createRange();
range.setStartAfter(lastHeader);
range.setEndBefore(header);
return range.toString().trim().length >= 600;
}
function placeInlineAds() {
const excludedContent = document.querySelectorAll('#ftl-article.branded-content, #ftl-article.sponsored');
if (excludedContent.length > 0) {
return;
}
const headers = Array.from(document.querySelectorAll('.content-html h2')).splice(1);
let globalIndex = 12;
for (let i = 0; i < headers.length; i++) {
if (!lastHeader || isHeaderEligible(headers[i])) {
const element = document.createElement('div');
element.id = 'div-gpt-ad-1435246566686-' + globalIndex;
element.classList.add('inline-display', 'dz2_inline-article-display');
element.setAttribute('data-gpt-slot', 'inline');
headers[i].before(element);
lastHeader = element;
globalIndex++;
}
}
}
function makeAds() {
handleSkybox();
placeInlineAds();
const script = document.createElement('script');
script.src = 'https://i6ByW9Zmz4ncxhHkb.ay.delivery/manager/i6ByW9Zmz4ncxhHkb';
script.type = 'text/javascript';
script.referrerPolicy = 'no-referrer-when-downgrade';
document.head.appendChild(script);
window.googletag.cmd.push(function() {
const containers = document.querySelectorAll('div[data-gpt-slot]');
for (let container of containers) {
const div = container.getAttribute('data-gpt-slot');
const meta = metadata[div];
if (meta.minWidthToShow && width < meta.minWidthToShow) {
continue;
}
window.googletag.pubads().setTargeting('hostname', window.location.hostname);
Object.keys(gptTags).forEach(function(key) {
window.googletag.pubads().setTargeting(key, gptTags[key]);
});
window.googletag.pubads().addEventListener('slotRenderEnded', (event) => {
window.requestAnimationFrame(() => {
var slotId = event.slot.getSlotElementId();
if (!slotId.includes('__ayManagerEnv__')) {
return;
}
var className = slotId.split('__ayManagerEnv__')[0];
var slotName = className.replace('dz2_', '').replace('dz_', '').replace(/_\d+$/, '');
var unitName = meta.slot.replace('dz2_', '').replace('dz_', '').replace(/_\d+$/, '');
if (slotName !== unitName) {
return;
}
var elem = document.getElementById(slotId);
if (!elem) {
console.warn('Ad element missing', slotId);
return;
}
// Ad unit did not fill, collapse slot
if (event.isEmpty && elem.parentElement) {
elem.parentElement.style.display = 'none';
}
});
});
}
GAM_setUpSixSenseTargeting();
});
}
</script>
<script async>// InMobi Choice. Consent Manager Tag v3.0 (for TCF 2.2)
!function(){var e=window.location.hostname,t=document.createElement("script"),n=document.getElementsByTagName("script")[0],a="https://cmp.inmobi.com".concat("/choice/","vPn77x7pBG57Y","/","dzone.com","/choice.js?tag_version=V3"),p=0;t.async=!0,t.type="text/javascript",t.src=a,n.parentNode.insertBefore(t,n),function(){for(var e,t="__tcfapiLocator",n=[],a=window;a;){try{if(a.frames[t]){e=a;break}}catch(e){}if(a===window.top)break;a=a.parent}e||(!function e(){var n=a.document,p=!!a.frames[t];if(!p)if(n.body){var s=n.createElement("iframe");s.style.cssText="display:none",s.name=t,n.body.appendChild(s)}else setTimeout(e,5);return!p}(),a.__tcfapi=function(){var e,t=arguments;if(!t.length)return n;if("setGdprApplies"===t[0])t.length>3&&2===t[2]&&"boolean"==typeof t[3]&&(e=t[3],"function"==typeof t[2]&&t[2]("set",!0));else if("ping"===t[0]){var a={gdprApplies:e,cmpLoaded:!1,cmpStatus:"stub"};"function"==typeof t[2]&&t[2](a)}else"init"===t[0]&&"object"==typeof t[3]&&(t[3]=Object.assign(t[3],{tag_version:"V3"})),n.push(t)},a.addEventListener("message",(function(e){var t="string"==typeof e.data,n={};try{n=t?JSON.parse(e.data):e.data}catch(e){}var a=n.__tcfapiCall;a&&window.__tcfapi(a.command,a.version,(function(n,p){var s={__tcfapiReturn:{returnValue:n,success:p,callId:a.callId}};t&&(s=JSON.stringify(s)),e&&e.source&&e.source.postMessage&&e.source.postMessage(s,"*")}),a.parameter)}),!1))}(),function(){const e=["2:tcfeuv2","6:uspv1","7:usnatv1","8:usca","9:usvav1","10:uscov1","11:usutv1","12:usctv1"];window.__gpp_addFrame=function(e){if(!window.frames[e])if(document.body){var t=document.createElement("iframe");t.style.cssText="display:none",t.name=e,document.body.appendChild(t)}else window.setTimeout(window.__gpp_addFrame,10,e)},window.__gpp_stub=function(){var t=arguments;if(__gpp.queue=__gpp.queue||[],__gpp.events=__gpp.events||[],!t.length||1==t.length&&"queue"==t[0])return __gpp.queue;if(1==t.length&&"events"==t[0])return __gpp.events;var n=t[0],a=t.length>1?t[1]:null,p=t.length>2?t[2]:null;if("ping"===n)a({gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:e,cmpId:10,sectionList:[],applicableSections:[-1],gppString:"",parsedSections:{}},!0);else if("addEventListener"===n){"lastId"in __gpp||(__gpp.lastId=0),__gpp.lastId++;var s=__gpp.lastId;__gpp.events.push({id:s,callback:a,parameter:p}),a({eventName:"listenerRegistered",listenerId:s,data:!0,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:e,cmpId:10,sectionList:[],applicableSections:[-1],gppString:"",parsedSections:{}}},!0)}else if("removeEventListener"===n){for(var i=!1,o=0;o<__gpp.events.length;o++)if(__gpp.events[o].id==p){__gpp.events.splice(o,1),i=!0;break}a({eventName:"listenerRemoved",listenerId:p,data:i,pingData:{gppVersion:"1.1",cmpStatus:"stub",cmpDisplayStatus:"hidden",signalStatus:"not ready",supportedAPIs:e,cmpId:10,sectionList:[],applicableSections:[-1],gppString:"",parsedSections:{}}},!0)}else"hasSection"===n?a(!1,!0):"getSection"===n||"getField"===n?a(null,!0):__gpp.queue.push([].slice.apply(t))},window.__gpp_msghandler=function(e){var t="string"==typeof e.data;try{var n=t?JSON.parse(e.data):e.data}catch(e){n=null}if("object"==typeof n&&null!==n&&"__gppCall"in n){var a=n.__gppCall;window.__gpp(a.command,(function(n,p){var s={__gppReturn:{returnValue:n,success:p,callId:a.callId}};e.source.postMessage(t?JSON.stringify(s):s,"*")}),"parameter"in a?a.parameter:null,"version"in a?a.version:"1.1")}},"__gpp"in window&&"function"==typeof window.__gpp||(window.__gpp=window.__gpp_stub,window.addEventListener("message",window.__gpp_msghandler,!1),window.__gpp_addFrame("__gppLocator"))}();var s=function(){var e=arguments;typeof window.__uspapi!==s&&setTimeout((function(){void 0!==window.__uspapi&&window.__uspapi.apply(window.__uspapi,e)}),500)};if(void 0===window.__uspapi){window.__uspapi=s;var i=setInterval((function(){p++,window.__uspapi===s&&p<3?console.warn("USP is not accessible"):clearInterval(i)}),6e3)}}();
</script>
<script async>
(function(w, d, s, l, i) {
w[l] = w[l] || [];
w[l].push({'gtm.start': new Date().getTime(), event: 'gtm.js'});
var f = d.getElementsByTagName(s)[0], j = d.createElement(s), dl = l != 'dataLayer' ? '&l=' + l : '';
j.async = true;
j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
f.parentNode.insertBefore(j,f);
})(window, document, 'script', 'dataLayer', 'GTM-K25QL22');
</script>
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-410289-1', 'auto');
ga('require', 'linkid', 'linkid.js');
ga('require', 'GTM-TSD9TZP');
ga('set', 'siteSpeedSampleRate', 25);
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
<script async>var analytics = {
'dimension1': 'Cloud Architecture',
'dimension2': 'article/analysis',
'dimension3': '2024-10-14',
'dimension4': '0',
'dimension5': '',
'dimension7': 'Disaster recovery, Infrastructure, cloud, systems, terraform',
'dimension8': 'jojustin',
'dimension9': 'undefined',
'dimension10': 'IBM'
};
if (window.ga) {
Object.keys(analytics).forEach(function(key) {
window.ga('set', key, analytics[key]);
});
window.ga('send', 'pageview');
}</script>
<script src="https://dz2cdn1.dzone.com/themes/dz20/lib/static/jquery/jquery.min.js"></script>
<script async src="https://dz2cdn1.dzone.com/themes/dz20/lib/static/bootstrap/bootstrap.min.js"></script>
<script>
function loadScript(src) {
return new Promise(function (resolve, reject) {
const s = document.createElement('script');
s.src = src;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
}
function loadStyle(href) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = href;
document.head.appendChild(link);
}
function loadScriptsSync(deferred) {
var p = Promise.resolve();
for (var i = 0; i < deferred.length; i++) {
let script = deferred[i];
p = p.then(function() {
return loadScript(script);
});
}
return p;
}
function loadStyles() {
const deferred = [
'https://dz2cdn1.dzone.com/themes/dz20/lib/codemirror/lib/codemirror.css',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/comments/styles.css',
'https://dz2cdn1.dzone.com/themes/dz20/lib/froala3/css/froala_editor.pkgd.min.css',
'https://dz2cdn1.dzone.com/themes/dz20/lib/froala3/css/themes/gray.min.css',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/article/mini-profile.css'
];
for (var i = 0; i < deferred.length; i++) {
loadStyle(deferred[i]);
}
}
window.addEventListener('load', function(_event) {
loadStyles();
loadScriptsSync([
'https://dz2cdn1.dzone.com/themes/dz20/lib/lazysizes.min.js',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/article/codeblocks.js',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/article/activity-bar.js',
'https://dz2cdn1.dzone.com/themes/dz20/lib/froala3/js/froala_editor.pkgd.min.js',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/froala/content.js',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/comments/content.js',
'https://dz2cdn1.dzone.com/themes/dz20/ftl/article/content.js'
]);
});
</script>
</body>
</html>