<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Cloud Nine Apps</title>
	<atom:link href="https://cloudnineapps.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://cloudnineapps.com</link>
	<description>Simplifying Technology</description>
	<lastBuildDate>Sat, 11 Feb 2023 22:22:34 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.4.16</generator>

<image>
	<url>https://i2.wp.com/cloudnineapps.com/wp-content/uploads/cropped-CloudNineApps_favicon-2.png?fit=32%2C32&#038;ssl=1</url>
	<title>Cloud Nine Apps</title>
	<link>https://cloudnineapps.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">136749396</site>	<item>
		<title>How To Design A Cross-Platform Mobile Application?</title>
		<link>https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/</link>
					<comments>https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Fri, 01 Jan 2021 00:32:37 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4547</guid>

					<description><![CDATA[<p>How To Design A Cross-Platform Mobile Application? Mobile applications have taken a center stage for the past few years, and with the continuous improvements in mobile technology, we will see more and more applications embracing the mobile platform. However, as&#8230;&#160;<a href="https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/">How To Design A Cross-Platform Mobile Application?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Design A Cross-Platform Mobile Application?</h1>
<p>Mobile applications have taken a center stage for the past few years, and with the continuous improvements in mobile technology, we will see more and more applications embracing the mobile platform. However, as an Architect and a developer, building a mobile application that will work across multiple platforms, and yet keep the code as sleek as possible is a daunting task. This was the challenge I faced when designing the <a href="https://cloudnineapps.com/products/mobile/shopping-guru/" target="_blank" rel="noopener noreferrer">Shopping Guru app</a> that helps in making the most out of your online purchases. In this article, I will cover how I went about making this cross-platform app with a high amount of code reusability.</p>
<h2>Cross-Platform Mobile Application Key Challenges</h2>
<p>For the sake of discussion, I&#8217;m summarizing the two core requirements for the Shopping Guru app so that we can understand the challenges and the key aspects of the design better.</p>
<ul>
<li>Do periodic checks to generate price drop and product availability alerts.</li>
<li>Facilitate goal-driven purchases by organizing these into projects. For example, create a project to set up a home theater.</li>
</ul>
<p>We briefly touched upon a couple of challenges in the introduction. But, let&#8217;s highlight the key challenges keeping the 2 dominant mobile platforms &#8211; <strong>iOS</strong> and <strong>Android</strong>.</p>
<ul>
<li>How to improve the code reusability? A big part of this question is how to use the same programming language? As we know, iOS supports Swift and Objective-C. Whereas, Android supports Java and Kotlin.</li>
<li>How to manage the app data in the cloud? For example, iOS offers iCloud functionality to store data. But, the moment you add Android into the mix, you do not want to have multiple ways of managing data in the cloud, especially, if your app has cloud-based processes that need access to this data. In the case of Shopping Guru, we needed access to the data to generate price drop alerts and to check whether a previously unavailable product is now available.</li>
<li>How to handle platform-specific interactions that originate &#8220;from&#8221; the common code? For example, when a price drop occurs generate a notification. The price drop check can be done in a platform-independent reusable code. However, the notification has to be generated using platform-specific features.</li>
<li>How to handle resources, such as externalized text and images?</li>
</ul>
<p>As you can see, if we don&#8217;t get hold of these aspects early on, the code could get quite messy.</p>
<h2>Application Architecture</h2>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?ssl=1"><img class="alignnone wp-image-4550 size-large" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=640%2C303&#038;ssl=1" alt="" width="640" height="303" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=1024%2C484&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=300%2C142&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=768%2C363&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=320%2C151&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=640%2C302&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=360%2C170&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=720%2C340&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=1080%2C510&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?resize=800%2C378&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/Technology/How_To_Design_A_Cross_Platform_Mobile_Application/ShoppingGuru_Architecture_Diagram.png?w=1168&amp;ssl=1 1168w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>After doing a few prototypes, I decided to split the application into 2 parts.</p>
<ol>
<li><strong>Mobile App</strong>: This is the app itself that contains primarily the user interaction code with basic logic.</li>
<li><strong>Cloud-based REST API</strong>: This handles the core business logic and provides additional capabilities to improve performance, such as caching and throttling calls to the Vendor API. The Vendor API is used to search and retrieve items.</li>
</ol>
<h3>Mobile Application Design</h3>
<p>The app comprises the following key components.</p>
<ul>
<li><strong>UI</strong>: The user interface and associated code. This layer is implemented separately for iOS and Android. The majority of the application code is written in Java. For Android, that&#8217;s pretty straight-forward. And, for iOS, I used <a href="https://multi-os-engine.org/" target="_blank" rel="noopener noreferrer">Multi-OS Engine</a>, which provides a Java runtime on iOS and makes it possible to write pretty much all of the code in Java. You still need to use Xcode to create the storyboard and generate the skeleton code (such as the controller header and implementation files). From that point, you can use Multi-OS Engine&#8217;s IDE plugins to generate Java artifacts. It&#8217;s free and the app performance was reasonable.</li>
<li><strong>Core</strong>: This component provides common business logic and maximum code reusability. It also handles common resources, such as externalized text, images, and configuration files. For outgoing calls from the Core module to platform-specific implementation, I decided to have specific interfaces that will be implemented by the respective platform-specific module. For example, both Android and iOS modules implement a <span style="font-family: courier new, courier, monospace;">NotificationManager</span> interface to provide notification management functionality. The UI code passes these module instances to the Core module at initialization time.</li>
<li><strong>Data Refresh</strong>: This component helps in fetching prices periodically, especially when the app is running in the foreground. Again, this is a reusable component.</li>
<li>The app uses the following custom libraries.
<ul>
<li><strong>NetworkMonitor</strong>: This is used for monitoring the network status, such as when the device is connected to WiFi versus when its connected to the cellular network. Depending on the type of connectivity, the app automatically switches network usage to avoid/minimize cellular data usage.</li>
<li><strong>AnalyticsManager</strong>: This is used to publish opt-in app usage metrics with user consent.</li>
</ul>
</li>
</ul>
<p>With this approach, I could significantly improve code and resource reusability.</p>
<h3>REST API Design</h3>
<p>The REST API acts as the brain of the solution and comprises the following key components.</p>
<ul>
<li>The API Gateway + Lambda combination provides the REST API layer that the app would use for needs like searching items and retrieving item prices. It interacts with the Vendor API behind the scenes on a need basis to fetch the latest data. Also, it can do price drop and product availability checks periodically.</li>
<li>DynamoDB is used to cache the frequently accessed data.</li>
<li>It also offers a platform-agnostic way of managing app data. In fact, for the most part, the cloud-based components do not even care about the device&#8217;s actual platform.</li>
</ul>
<p>Apart from resolving some of the challenges cited earlier, cloud-based components provide additional flexibility to add improvements and enhancements that do not require changes to the mobile app. This saves significant time to deliver enhancements to the end-users.</p>
<h2>Development Setup</h2>
<ul>
<li>I chose Android Studio as the core IDE since it is quite convenient for Android development. Besides, Multi-OS Engine offers a neat plugin to generate Java artifacts.</li>
<li>Xcode is used on a need basis when editing the storyboard and creating initial files. Also, it is used to publish builds to App Store Connect.</li>
<li>The build uses the gradle framework. Each module has a <span style="font-family: courier new, courier, monospace;">build.gradle</span> file.</li>
<li>For cloud deployment, I am using the AWS CloudFormation templates. This makes it easy to add more regions, as needed, literally in a matter of minutes!</li>
</ul>
<h2>Resources</h2>
<ul>
<li><a href="https://multi-os-engine.org/start/" target="_blank" rel="noopener noreferrer">Multi-OS Engine Getting Started Guide</a></li>
<li><a href="https://medium.com/swlh/how-to-design-applications-for-cloud-saas-88eab310ffad" target="_blank" rel="noopener noreferrer">How To Design Applications For Cloud (SaaS)?</a></li>
<li><a href="https://medium.com/swlh/how-to-create-a-multi-tier-stack-using-aws-cloudformation-f8f2685d27c6" target="_blank" rel="noopener noreferrer">How To Create a Multi-Tier Stack Using AWS CloudFormation?</a></li>
</ul>
<p>&nbsp;</p>
<p>Developing a cross-platform mobile application requires a focused approach to consistently identify platform-specific versus reusable code. Once you establish this basic rule of thumb, you can extend it further to identify components that can be reused across multiple applications (like the <span style="font-family: courier new, courier, monospace;">NetworkMonitor</span> and <span style="font-family: courier new, courier, monospace;">AnalyticsManager</span> in this article). And, I hope this article gives you a good enough starting point to build a prototype for your mobile application and see if it would meet your needs.</p>
<p>Happy developing!<br />
&#8211; Nitin</p>
<p><em>If you liked this post, you will find my <a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/" rel="noopener noreferrer">AWS Advanced For Developers</a> course helpful that focuses on many such best practices and techniques to design and deploy real-world applications in AWS.</em></p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-design-a-cross-platform-mobile-application%2F&amp;linkname=How%20To%20Design%20A%20Cross-Platform%20Mobile%20Application%3F" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-design-a-cross-platform-mobile-application%2F&amp;linkname=How%20To%20Design%20A%20Cross-Platform%20Mobile%20Application%3F" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-design-a-cross-platform-mobile-application%2F&amp;linkname=How%20To%20Design%20A%20Cross-Platform%20Mobile%20Application%3F" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-design-a-cross-platform-mobile-application%2F&amp;linkname=How%20To%20Design%20A%20Cross-Platform%20Mobile%20Application%3F" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-design-a-cross-platform-mobile-application%2F&#038;title=How%20To%20Design%20A%20Cross-Platform%20Mobile%20Application%3F" data-a2a-url="https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/" data-a2a-title="How To Design A Cross-Platform Mobile Application?"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/">How To Design A Cross-Platform Mobile Application?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/technology/how-to-design-a-cross-platform-mobile-application/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4547</post-id>	</item>
		<item>
		<title>Shopping Guru 1.2 Released</title>
		<link>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/</link>
					<comments>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Sat, 26 Dec 2020 22:47:40 +0000</pubDate>
				<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4539</guid>

					<description><![CDATA[<p>Shopping Guru 1.2 Released Following are the highlights of this release. Share an item with Shopping Guru from a product page on Amazon’s mobile application or website. Product Availability Alerts: When the demand is high, several commonly needed items become&#8230;&#160;<a href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/">Shopping Guru 1.2 Released</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Shopping Guru 1.2 Released</h1>
<p><a href="https://cloudnineapps.com/products/mobile/shopping-guru/"><img class="wp-image-2666 size-thumbnail alignleft" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=150%2C150&#038;ssl=1" alt="" width="150" height="150" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=150%2C150&amp;ssl=1 150w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=300%2C300&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=768%2C768&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=320%2C320&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=640%2C640&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=360%2C360&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=720%2C720&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=800%2C800&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?w=1024&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=270%2C270&amp;ssl=1 270w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=200%2C200&amp;ssl=1 200w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=100%2C100&amp;ssl=1 100w" sizes="(max-width: 150px) 100vw, 150px" data-recalc-dims="1" /></a>Following are the highlights of this release.</p>
<ul>
<li>Share an item with Shopping Guru from a product page on Amazon’s mobile application or website.</li>
<li>Product Availability Alerts: When the demand is high, several commonly needed items become unavailable quickly. Just share the item that is currently unavailable from Amazon&#8217;s mobile application or website, and Shopping Guru will alert you when the item becomes available.</li>
<li>Launch Amazon’s mobile app (if installed) when buy item is clicked.</li>
<li>Major improvements to price checks and generating price drop notifications.</li>
</ul>
<p><a href="https://cloudnineapps.com/products/mobile/shopping-guru/">Check it out</a> now! We would love to hear your feedback.</p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-2-released%2F&amp;linkname=Shopping%20Guru%201.2%20Released" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-2-released%2F&amp;linkname=Shopping%20Guru%201.2%20Released" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-2-released%2F&amp;linkname=Shopping%20Guru%201.2%20Released" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-2-released%2F&amp;linkname=Shopping%20Guru%201.2%20Released" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-2-released%2F&#038;title=Shopping%20Guru%201.2%20Released" data-a2a-url="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/" data-a2a-title="Shopping Guru 1.2 Released"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/">Shopping Guru 1.2 Released</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-2-released/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4539</post-id>	</item>
		<item>
		<title>How To Approach The Internal Documentation Of Your Software Projects?</title>
		<link>https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/</link>
					<comments>https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Wed, 05 Feb 2020 11:25:35 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4452</guid>

					<description><![CDATA[<p>How To Approach The Internal Documentation Of Your Software Projects? Many Software Architects, Developers, and Leads face this question for their projects &#8211; whether they should document their projects? If yes, how much? No, we are not talking about the&#8230;&#160;<a href="https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/">How To Approach The Internal Documentation Of Your Software Projects?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Approach The Internal Documentation Of Your Software Projects?</h1>
<p>Many Software Architects, Developers, and Leads face this question for their projects &#8211; whether they should document their projects? If yes, how much? No, we are not talking about the required documentation that almost every software project needs, like the customer-facing documentation. By &#8220;internal documentation&#8221;, I am talking about technical documentation like Architecture and Design documents. In this post, we will discuss how to approach such internal documentation.</p>
<h2>Why Document Your Project?</h2>
<p>This is the most important question. Simply put, what is your intent behind documentation? Are you planning to use it as a tool that can help you build more quality software or are you simply putting together some artifacts for the sake of it? And, this is not just a question for the Architects and Designers, but also the entire team. After all, when you are investing time and effort in the documentation, most of the team should benefit from it. Projects that take the approach of using documentation as a tool to build more quality software not only benefit from it, but these have more useful documentation.</p>
<h3>Pros of Technical Documentation</h3>
<p>The following are some of the common benefits of having technical documentation.</p>
<ul>
<li>It helps validate the approach, design, and implementation.</li>
<li>It can help establish the core concepts and avoid common misunderstandings.</li>
<li>The same artifact can benefit multiple aspects of the software life cycle. Remember that the same document may be consumed in different ways by different team members. For example, while a developer may look at it for their implementation, a quality assurance team member can use it for writing their test cases.</li>
<li>It can significantly help in ramping up new team members who join the project later.</li>
<li>It establishes transparency in sharing information that could benefit the entire team.</li>
<li>By keeping it up-to-date, it can help avoid redundant communication.</li>
</ul>
<h3>Cons of Technical Documentation</h3>
<p>Of course, documentation comes at a cost. These are not necessarily cons of documentation but are associated with it.</p>
<ul>
<li>It requires a time investment.</li>
<li>It runs the risk of getting outdated as the project progresses. This is often the case when documentation is produced for the sake of it but is not being used for anything meaningful.</li>
</ul>
<p>So, as you can see, it all boils down to the point about the purpose of the documentation.</p>
<h2>How To Approach Technical Documentation?</h2>
<p>I am a big believer in using documentation as a tool to deliver quality software. Hence, I like to invest time to make it more meaningful. Here are some useful tips that I like to consider for the documentation.</p>
<ul>
<li><strong>Establish the core concepts</strong>: Having a simple section like glossary is good. But, often you, as a designer, may have some core concepts that you would like the team to understand. Just like in the business world, there are key driving factors, there are certain core concepts that are key to the functioning of your application. For example, specific data model elements, algorithmic constructs that can help the team understand how the system is architected and what was the thought process behind it. It is interesting to come back to this section a year later and find whether these are still applicable!</li>
<li><strong>Organize effectively</strong>: Avoid clubbing multiple types of content in the same section. It not only makes it harder to understand, but it could create confusion and make it difficult for other team members to extract information. For example, instead of including data model, deployment, performance altogether, consider splitting these into separate sections. For more complex projects, it may be worth having dedicated documentation for certain components/services and having links to these from the overall project-level documentation. This way, team members focused on those components can find information more easily. It would also make it easier to delegate ownership of maintaining this documentation.</li>
<li><strong>Be concise</strong>: The good thing when you write is you can try to articulate your thoughts as concisely as possible. I like to use bullets over paragraphs especially when the topic is dense.</li>
<li><strong>Keep it simple</strong>: That goes without saying. Avoid the use of complex words and jargon that are not helpful. Of course, if some complex terms are vital from an understanding perspective, use these, but make sure that these have been clarified.</li>
</ul>
<h3>What Should I Include In My Software Design Document?</h3>
<p>A Software Design Document (a.k.a. SDD) is a <strong>living commentary</strong> of your project. The following are some key pieces of information that I would like to include in an SDD.</p>
<p><span style="text-decoration: underline;">Note</span>: I talk about multiple diagrams as each diagram helps in analyzing the application differently, and collectively these help in gaining a more complete picture.</p>
<ul>
<li><strong>Glossary</strong>: This captures the key terms that consumers of the documentation should be familiar with. For example, any important abbreviations you are using throughout the documentation.</li>
<li><strong>Architecture Overview</strong>: An overview of the System Architecture. This is a very high-level blueprint of your application, such as an n-tier architecture that will typically not change much over the life span of the application.</li>
<li><strong>Key Concepts</strong>: We talked about these earlier in this post. This section should cover the key concepts and how these work together to make your application function. Also, coming up with meaningful names for these concepts can often help you convey a specific point easily as opposed to always explain what you are talking about.</li>
<li><strong>High-Level Design</strong>: This should capture the overall system design, key components, and their dependencies. Often a <a href="https://en.wikipedia.org/wiki/Component_diagram" target="_blank" rel="noopener noreferrer">UML Component Diagram</a> can come in handy here. The idea here is to give sufficient guidance to individual components&#8217; leads to understanding how they fit in the overall picture. At the same time, giving them at least some level of flexibility in their specific component design, as appropriate.</li>
<li><strong>Deployment Diagram</strong>: If there is one diagram you must-have in almost every SDD, then this is the one. It helps in establishing key details like deployment nodes, which components will run on these, ports exposed, protocols used, and the direction of communication. This is often accomplished via a <a href="https://en.wikipedia.org/wiki/Deployment_diagram" target="_blank" rel="noopener noreferrer">UML Deployment Diagram</a>.</li>
<li><strong>Data Model</strong>: This is at the heart of many enterprise applications. At a minimum, this should include key entities and their relationships. Often, this will be the input for the database implementation. <a href="https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model" target="_blank" rel="noopener noreferrer">Entity-relationship Diagrams</a> or ER Diagrams are often used to capture this.</li>
<li><strong>Class Diagrams</strong>: Having one or more <a href="https://en.wikipedia.org/wiki/Class_diagram" target="_blank" rel="noopener noreferrer">Class Diagrams</a> that cover the key classes and their relationships can help the team members build a better understanding. Here, you should focus on core classes that contain business logic and avoid cluttering with classes that are only relevant from the data perspective. Those would typically have been covered in the Data Model anyway.</li>
<li><strong>Interaction Model</strong>: This helps in understanding component interaction in chronological order. This is often captured via <a href="https://en.wikipedia.org/wiki/Sequence_diagram" target="_blank" rel="noopener noreferrer">UML Sequence Diagrams</a>.</li>
<li><strong>Compatibility Matrix</strong>: If your application has specific compatibility requirements, such as operating system version, library versions, etc it is worth capturing these. These details are extremely important for testing as well as for customer documentation.</li>
<li><strong>Dependencies</strong>: Any third-party libraries or other dependencies that your application requires. This is important for technical aspects like builds. It is also important for legal because, at times, developers may pick up a library that may not be the best choice from a legal standpoint. So, the sooner you can jot down this list and get clearance from stakeholders, the better.</li>
<li><strong>Performance and Sizing</strong>: What are the sizing recommendations and what performance objectives and criteria do the design cater to? The answer may not be always simple and may require a few iterations. However, the point is to have at least some level of guidance and tweak it based on learnings.</li>
<li><strong>Security</strong>: Although other sections may touch upon it, it is important to make this section and address any specific security measures implemented in the application. This could be the use of secured protocols, network configurations, even some operational aspects like regular scanning and detection. This is not an operational document but should give guidance to the Operations team so that they know what measures they should have in place to secure the application.</li>
<li><strong>Enterprise Readiness</strong>: This covers various other aspects like high availability, accessibility, etc.</li>
<li><strong>Install and Upgrade</strong>: This section should cover considerations for fresh installation and upgrades. It is worth including any specific design considerations, such as the backward compatibility of the data model.</li>
<li><strong>Revision History</strong>: Finally, a section that contains the timestamp, the change author and a quick comment describing the change.</li>
</ul>
<p>The following are some not so commonly used sections. But, I like to use these in my SDDs as this helps bring in a lot more clarity and enabling various teams (including the support teams).</p>
<ul>
<li><strong>Developer Notes</strong>: This section contains useful tips and information on the code-level information. For example, how multi-threading should be used for a specific component, use of tokens to identify a request end-to-end, etc.</li>
<li><strong>Logging</strong>: Include specific patterns for details like understanding the flow, identifying a request, etc. Sample log snippets also can be extremely helpful.</li>
<li><strong>Troubleshooting</strong>: Provide information on how to troubleshoot the application. This should cover things like log locations, how to analyze logs, other system parameters to analyze, etc. If you can take a few key scenarios, that can also be helpful.</li>
<li><strong>Common Problems and Solutions</strong>: This is useful to capture the commonly observed issues and provide guidance on how to resolve them. As you can imagine, sections like these will continue to grow and can provide extremely useful information for the support knowledgebase.</li>
</ul>
<p>There are a lot of areas to cover and not everything needs to be done on day one. However, having place holder sections and updating these over time can help you in building useful documentation.</p>
<h2>Handling Future Updates To Documentation</h2>
<p>Keeping documentation up-to-date is critical to ensure it continues to be an effective tool. Good checkpoints when you can ensure that the documentation is updated.</p>
<ul>
<li>Any important technical assumptions are introduced or changed</li>
<li>Agile iteration boundaries</li>
<li>When new features are developed</li>
<li>When new major release begins</li>
</ul>
<h2>Conclusion</h2>
<p>As we can see from this post, technical or internal documentation can be a quite effective tool in building quality software and keeping teams in sync. Hence, instead of looking at it as an overhead, look at it as an investment that will pay you off as you embark on your software journey.</p>
<p>Happy developing!<br />
&#8211; Nitin</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-approach-the-internal-documentation-of-your-software-projects%2F&amp;linkname=How%20To%20Approach%20The%20Internal%20Documentation%20Of%20Your%20Software%20Projects%3F" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-approach-the-internal-documentation-of-your-software-projects%2F&amp;linkname=How%20To%20Approach%20The%20Internal%20Documentation%20Of%20Your%20Software%20Projects%3F" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-approach-the-internal-documentation-of-your-software-projects%2F&amp;linkname=How%20To%20Approach%20The%20Internal%20Documentation%20Of%20Your%20Software%20Projects%3F" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-approach-the-internal-documentation-of-your-software-projects%2F&amp;linkname=How%20To%20Approach%20The%20Internal%20Documentation%20Of%20Your%20Software%20Projects%3F" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Ftechnology%2Fhow-to-approach-the-internal-documentation-of-your-software-projects%2F&#038;title=How%20To%20Approach%20The%20Internal%20Documentation%20Of%20Your%20Software%20Projects%3F" data-a2a-url="https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/" data-a2a-title="How To Approach The Internal Documentation Of Your Software Projects?"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/">How To Approach The Internal Documentation Of Your Software Projects?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/technology/how-to-approach-the-internal-documentation-of-your-software-projects/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4452</post-id>	</item>
		<item>
		<title>How To Use AWS CloudWatch With On-Premise Application Components?</title>
		<link>https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/</link>
					<comments>https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Thu, 09 Jan 2020 11:27:36 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4424</guid>

					<description><![CDATA[<p>How To Use AWS CloudWatch With On-Premise Application Components? AWS CloudWatch offers centralized logging, monitoring, and analysis to make the developer&#8217;s job easier. A question that comes up for the Enterprise Applications that follow a hybrid cloud deployment (that is,&#8230;&#160;<a href="https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/">How To Use AWS CloudWatch With On-Premise Application Components?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Use AWS CloudWatch With On-Premise Application Components?</h1>
<p>AWS CloudWatch offers centralized logging, monitoring, and analysis to make the developer&#8217;s job easier. A question that comes up for the Enterprise Applications that follow a <strong>hybrid cloud</strong> deployment (that is, one or more of the application components reside on-premise) is how can we use CloudWatch logs for the on-premise components? Is it even possible? The short answer is yes. And, we will see in this post how to do that.</p>
<h2>Why Use CloudWatch For On-Premise Components?</h2>
<p>There are several benefits of using CloudWatch for On-Premise components.</p>
<ul>
<li><strong>Leverage from centralized logging</strong>: You can use the same capabilities for storing the logs centrally for the on-premise components that you are using for the rest of your Cloud-based components.</li>
<li><strong>Time Conversion</strong>: CloudWatch logs are stored in UTC. So, you do not have to worry about tedious conversions, which could often take up your precious time when analyzing logs across several components, especially if these are spread across geographically.</li>
<li><strong>Consistent Analysis</strong>: You can use the same tools and techniques that you are using for Cloud-based components.</li>
<li>Avoid issues like logs rollover or difficult to access logs. Often, on-premise components are managed by customers or other clients that may require some coordination and effort.</li>
</ul>
<h2>How To Publish To CloudWatch Logs From On-Premise Components?</h2>
<p>There are a couple of approaches to accomplish this.</p>
<ol>
<li><strong>Using the AWS CloudWatch Agent to publish logs</strong>: This can be extremely useful for on-premise components that follow an <em>appliance model</em> for deployment (such as a pre-baked image with the application components and dependencies). So, this approach is more configuration-centric and should not require code-level changes. Apart from log collection, the CloudWatch agent can also help in capturing system metrics (such as CPU and memory utilization).</li>
<li><strong>Using the CloudWatch Logs API to publish logs</strong>: This approach requires enhancing the code to use the CloudWatch Logs API to publish logs. Of course, you can make it a reusable module or consider using a third-party library. But, the point is this is a code-centric approach that offers more flexibility.</li>
</ol>
<p>In this post, we will be talking about using the CloudWatch Logs API. If you are interested in using the CloudWatch Agent, please refer to the <a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html" target="_blank" rel="noopener noreferrer">AWS CloudWatch Agent</a> documentation for details.</p>
<h3>Using The CloudWatch Logs API To Publish Logs</h3>
<p>The following code shows the CloudWatch Logs API usage.</p>
<pre class="lang:default decode:true" title="AWSCloudWatchLogsSampleClient.java">package com.cloudnineapps.samples.aws;

import java.util.ArrayList;
import java.util.List;

import com.amazonaws.auth.AWSCredentialsProvider;
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
import com.amazonaws.services.logs.AWSLogsClient;
import com.amazonaws.services.logs.AWSLogsClientBuilder;
import com.amazonaws.services.logs.model.CreateLogGroupRequest;
import com.amazonaws.services.logs.model.CreateLogStreamRequest;
import com.amazonaws.services.logs.model.DescribeLogGroupsRequest;
import com.amazonaws.services.logs.model.DescribeLogGroupsResult;
import com.amazonaws.services.logs.model.DescribeLogStreamsRequest;
import com.amazonaws.services.logs.model.DescribeLogStreamsResult;
import com.amazonaws.services.logs.model.InputLogEvent;
import com.amazonaws.services.logs.model.PutLogEventsRequest;
import com.amazonaws.services.logs.model.PutRetentionPolicyRequest;

/**
 * Sample client for AWS CloudWatch Logs API.
 */
public class AWSCloudWatchLogsSampleClient {

	/** The log group name. */
	private static final String LOG_GROUP = "/myapp/onprem/component-1";

	/** The log stream name. */
	private static final String LOG_STREAM = "app-log";
	
	/** The log retention period (in days). */
	private static final int LOG_RETENTION_PERIOD = 1;

	/** The AWS region. */
	private static String Region = "us-east-1";
	
	/** The CloudWatch client. */
	private static AWSLogsClient Client;
	
	
	/** Opens the CloudWatch log. */
	public static void openCloudWatchLog() throws Exception {
		AWSCredentialsProvider creds = new DefaultAWSCredentialsProviderChain();
		Client = (AWSLogsClient) AWSLogsClientBuilder.standard()
				     .withCredentials(creds)
				     .withRegion(Region)
				     .build();
		// Create and set up the log group if it doesn't exist
		DescribeLogGroupsRequest request = new DescribeLogGroupsRequest().withLogGroupNamePrefix(LOG_GROUP);
		DescribeLogGroupsResult result = Client.describeLogGroups(request);
		if (result.getLogGroups().isEmpty()) {
			CreateLogGroupRequest logGroupRequest = new CreateLogGroupRequest(LOG_GROUP);
			Client.createLogGroup(logGroupRequest);
			PutRetentionPolicyRequest policyRequest = new PutRetentionPolicyRequest(LOG_GROUP, LOG_RETENTION_PERIOD);
			Client.putRetentionPolicy(policyRequest);
			CreateLogStreamRequest logStreamRequest = new CreateLogStreamRequest(LOG_GROUP, LOG_STREAM);
			Client.createLogStream(logStreamRequest);
			log("Created the log group and the log stream.");
		}
	}
	
	/** Logs the specified message. */
	public static void log(String msg) throws Exception {
		// Retrieve the sequence token in the log stream
		DescribeLogStreamsRequest request = new DescribeLogStreamsRequest().withLogGroupName(LOG_GROUP).withLogStreamNamePrefix(LOG_STREAM);
		DescribeLogStreamsResult result = Client.describeLogStreams(request);
		String seqToken = result.getLogStreams().get(0).getUploadSequenceToken();

		// Write to the log stream
		List&lt;InputLogEvent&gt; logEvents = new ArrayList&lt;InputLogEvent&gt;();
		InputLogEvent logEvent = new InputLogEvent().withMessage(msg).withTimestamp(System.currentTimeMillis());
		logEvents.add(logEvent);
		PutLogEventsRequest logRequest = new PutLogEventsRequest(LOG_GROUP, LOG_STREAM, logEvents).withSequenceToken(seqToken);
		Client.putLogEvents(logRequest);
	}
		
	/** Main */
	public static void main(String[] args) throws Exception {
		System.out.println("Launching the application...");
		openCloudWatchLog();
		// Sample log statements
		log("Starting the app...");
		log("Another message");
		System.out.println("Execution completed.");
	}
}
</pre>
<p>Let&#8217;s walk through the code. You can check out the <strong>Resources</strong> section for the complete code (including the maven pom that can be used to compile and execute).</p>
<ul>
<li>The <span style="font-family: courier new, courier, monospace;">main()</span> method invokes the <span style="font-family: courier new, courier, monospace;">openCloudWatchLog()</span> method to initialize the CloudWatch Logs SDK client.</li>
<li>The <span style="font-family: courier new, courier, monospace;">openCloudWatchLog()</span> method checks if the required Log Group (<span style="font-family: courier new, courier, monospace;">/myapp/onprem/component-1</span>) exists using the <span style="font-family: courier new, courier, monospace;">DescribeLogGroupsRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.describeLogGroups()</span> call. If not, it creates the Log Group using the <span style="font-family: courier new, courier, monospace;">CreateLogGroupRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.createLogGroup()</span> call. We should always ensure that an appropriate log retention period is set on the log group to avoid accruing a huge log that can lead to a high cost. This is accomplished using the <span style="font-family: courier new, courier, monospace;">PutRetentionPolicyRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.putRetentionPolicy()</span> call. Then, we create the Log Stream using the <span style="font-family: courier new, courier, monospace;">CreateLogStreamRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.createLogStream()</span> call. The following screenshot shows the Log Group in the CloudWatch Console.<br />
<a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?ssl=1"><img class="alignnone size-large wp-image-4433" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=640%2C161&#038;ssl=1" alt="" width="640" height="161" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=1024%2C257&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=300%2C75&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=768%2C193&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=320%2C80&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=640%2C161&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=360%2C90&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=720%2C181&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=1080%2C271&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=800%2C201&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?resize=1280%2C321&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Group.png?w=1474&amp;ssl=1 1474w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></li>
<li>Here is a screenshot of the Log Stream under the Log Group.<br />
<a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?ssl=1"><img class="alignnone size-large wp-image-4431" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=640%2C161&#038;ssl=1" alt="" width="640" height="161" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=1024%2C258&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=300%2C76&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=768%2C194&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=320%2C81&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=640%2C161&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=360%2C91&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=720%2C181&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=1080%2C272&amp;ssl=1 1080w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=800%2C202&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?resize=1280%2C323&amp;ssl=1 1280w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Streams.png?w=1476&amp;ssl=1 1476w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></li>
<li>Next, the code uses the <span style="font-family: courier new, courier, monospace;">log()</span> method to log sample messages. It uses <span style="font-family: courier new, courier, monospace;">DescribeLogStreamsRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.describeLogStreams()</span> call to retrieve the Log Stream and fetch the upload sequence token. This token must be included when publishing logs (except for the very first publish). Then, we are creating an <span style="font-family: courier new, courier, monospace;">InputLogEvent</span> with the supplied message and timestamp. The log is published using the <span style="font-family: courier new, courier, monospace;">PutLogEventsRequest</span> and the <span style="font-family: courier new, courier, monospace;">Client.putLogEvents()</span> call. As you might have noticed, you do not have to publish individual log statements. You could very well add multiple <span style="font-family: courier new, courier, monospace;">InputLogEvent</span> objects to publish a batch of logs. The following screenshot demonstrates a sample run of the code.<br />
<a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?ssl=1"><img class="alignnone size-large wp-image-4432" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=640%2C230&#038;ssl=1" alt="" width="640" height="230" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=1024%2C368&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=300%2C108&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=768%2C276&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=320%2C115&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=640%2C230&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=360%2C129&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=720%2C259&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=1080%2C388&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=800%2C288&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?resize=1280%2C460&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Use_AWS_CloudWatch_With_On-Premise_App_Components/CW_Log_Stream_Content.png?w=1502&amp;ssl=1 1502w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></li>
</ul>
<h3>Using IAM Policy To Restrict Access To Specific Log</h3>
<p>As part of such a setup, it is important to use restrictive access so that the on-premise component can only access the specific log. The good thing is you can enforce this using IAM as follows.</p>
<ul>
<li>Create one or more IAM users for the on-premise components. Grant these users <strong>programmatic access only</strong>.</li>
<li>Create a custom policy (or assign an inline policy) like the one shown below and assign it to the above IAM user(s).</li>
</ul>
<pre class="lang:default decode:true">{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "CloudWatchLogGroupQueryAccess",
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Sid": "CloudWatchLogsAccess",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogGroup",
                "logs:PutRetentionPolicy",
                "logs:DescribeLogStreams",
                "logs:CreateLogStream",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:*:*:log-group:/myapp/onprem/*:log-stream:*"
        }
    ]
}</pre>
<p>This policy grants access to the required CloudWatch Logs API calls on the on-premise logs only.</p>
<h2>Best Practices For Publishing Logs From On-Premise Components</h2>
<p>The following are some key best practices to consider.</p>
<ul>
<li>Logging can easily get very network intensive. Hence, be quite judicious about which logs are sent to CloudWatch logs. For example, ERROR and WARNING logs are good candidates, but DEBUG is not typically.</li>
<li>Avoid logging any sensitive data. This is critical, and often not as well thought. For example, some of the things to avoid are logging passwords in plain text, users&#8217; Personally Identifiable Information (PII), and so on.</li>
<li>Always set an appropriate log retention period on the Log Group.</li>
<li>Use a well-defined naming convention for the Log Group and Log Streams. For example, <span style="font-family: courier new, courier, monospace;">/myapp/onprem/component-1</span>.</li>
<li>Use a restrictive IAM policy for the user that is used to publish logs, and ensure it has access to the component-specific logs only.</li>
<li>Prefer using application-specific IAM user(s) for logging across multiple applications. This way, you can track and manage access better.</li>
</ul>
<h2>Conclusion</h2>
<p>When designing hybrid cloud or on-premise components, evaluate publishing logs to CloudWatch. By following a few key best practices to ensure this is done in a manner that meets the application needs as well as enterprise readiness considerations like security and performance, this can be quite helpful in pro-active application monitoring and management.</p>
<h2>Resources</h2>
<ul>
<li><a href="https://github.com/cloudnineapps/AWSCloudWatchLogsSampleClient" target="_blank" rel="noopener noreferrer">AWSCloudWatchLogsSampleClient GitHub Repository</a></li>
</ul>
<p>&nbsp;</p>
<p>Happy logging!<br />
&#8211; Nitin</p>
<p><em>If you liked this post, you will find my <a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/" rel="noopener noreferrer">AWS Advanced For Developers</a> course helpful that focuses on many such best practices and techniques to design and deploy real-world applications in AWS.</em></p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-use-aws-cloudwatch-with-on-premise-application-components%2F&amp;linkname=How%20To%20Use%20AWS%20CloudWatch%20With%20On-Premise%20Application%20Components%3F" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-use-aws-cloudwatch-with-on-premise-application-components%2F&amp;linkname=How%20To%20Use%20AWS%20CloudWatch%20With%20On-Premise%20Application%20Components%3F" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-use-aws-cloudwatch-with-on-premise-application-components%2F&amp;linkname=How%20To%20Use%20AWS%20CloudWatch%20With%20On-Premise%20Application%20Components%3F" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-use-aws-cloudwatch-with-on-premise-application-components%2F&amp;linkname=How%20To%20Use%20AWS%20CloudWatch%20With%20On-Premise%20Application%20Components%3F" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-use-aws-cloudwatch-with-on-premise-application-components%2F&#038;title=How%20To%20Use%20AWS%20CloudWatch%20With%20On-Premise%20Application%20Components%3F" data-a2a-url="https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/" data-a2a-title="How To Use AWS CloudWatch With On-Premise Application Components?"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/">How To Use AWS CloudWatch With On-Premise Application Components?</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/cloud-computing/how-to-use-aws-cloudwatch-with-on-premise-application-components/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4424</post-id>	</item>
		<item>
		<title>How To Create A Multi-Tier Stack Using AWS CloudFormation</title>
		<link>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/</link>
					<comments>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Wed, 01 Jan 2020 11:24:08 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4405</guid>

					<description><![CDATA[<p>How To Create A Multi-tier Stack Using AWS CloudFormation? AWS CloudFormation (CFN) makes it easy to deploy and manage your application infrastructure as an atomic unit using CloudFormation templates. In this article, we will cover how to use CFN to&#8230;&#160;<a href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/">How To Create A Multi-Tier Stack Using AWS CloudFormation</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Create A Multi-tier Stack Using AWS CloudFormation?</h1>
<p>AWS CloudFormation (CFN) makes it easy to deploy and manage your application infrastructure as an atomic unit using CloudFormation templates. In this article, we will cover how to use CFN to create a multi-tier stack. We will also see how to handle different deployment variations, such as a full-blown production stack with a load balancer, and a smaller footprint development stack using the same CFN template! Lastly, I will also highlight some important tips when designing the CFN templates for your applications.</p>
<p><span style="text-decoration: underline;">Note</span>: If you are new to CloudFormation, I highly recommend reading the <a href="https://medium.com/swlh/aws-cloudformation-an-architects-best-friend-79526f60abf1" target="_blank" rel="nofollow noreferrer noopener">AWS CloudFormation &#8211; An Architect&#8217;s Best Friend</a> first to familiarize yourself with the basics.</p>
<h2>Identify The Application Deployment Models</h2>
<p>Before you start designing the CFN template, it is important to understand in which all possible ways the application can be deployed. At a minimum, identify the key deployment models. For example, what would a typical development deployment look like? Which resources would be needed and what are their configurations? Likewise, for production. Having these details upfront has several benefits.</p>
<ul>
<li>You will have a clear understanding of the legitimate combinations in which the application can be deployed.</li>
<li>You can then delve into the resource configurations and addressing other key aspects like security.</li>
<li>Lastly, you can ensure that the deployment models are as cost-optimal as possible. For example, the development stack may have the smallest footprint possible to keep cost low versus the production stack that may have a larger footprint.</li>
</ul>
<p>Let&#8217;s take a look at our sample multi-tier stack.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?ssl=1" target="_blank" rel="noopener noreferrer"><img class="alignright wp-image-4409 size-medium" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=219%2C300&#038;ssl=1" alt="" width="219" height="300" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=219%2C300&amp;ssl=1 219w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=768%2C1051&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=748%2C1024&amp;ssl=1 748w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=320%2C438&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=640%2C876&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=360%2C493&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=720%2C986&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=197%2C270&amp;ssl=1 197w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?resize=300%2C411&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_A_Multi-Tier_Stack_Using_AWS_CloudFormation/Multi_Tier_Stack.png?w=770&amp;ssl=1 770w" sizes="(max-width: 219px) 100vw, 219px" data-recalc-dims="1" /></a></p>
<ul>
<li>For the sake of discussion, we will cover 2 deployment models: Development and Production.</li>
<li>The <strong>Production</strong> deployment will comprise of a public-facing load balancer, which will be backed by 2 web-tier EC2 instances running Apache. These instances will talk to the EC2 instance hosting the app-tier running tomcat.</li>
<li>Security Groups will be used for access control. The <span style="font-family: courier new, courier, monospace;">PublicWebSecurityGroup</span> will be assigned to the web-tier and the <span style="font-family: courier new, courier, monospace;">AppSecurityGroup</span> will be assigned to the app-tier. Now, you may have noticed the <span style="font-family: courier new, courier, monospace;">PrivateWebSecurityGroup</span>. Can you guess what&#8217;s that for? Perhaps you got it. It is the Security Group created for the Production stack to ensure that the web-tier EC2 instances are only accessible via the load balancer and not exposed publicly.</li>
<li>The <strong>Development</strong> deployment of the stack will comprise of a single web-tier EC2 instance and a single app-tier EC2 instance.</li>
</ul>
<p>So, as you can see, this seemingly simple stack deployment can also become complex considering the different deployment models. But, not to worry. CFN provides us several useful capabilities to make this work.</p>
<h2>The Multi-Tier Stack CFN Template</h2>
<p>Here is the CFN template.</p>
<pre class="lang:default decode:true" title="Multi_Tier_Stack.json">{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "A multi-tier stack instance.",
  "Parameters": {
    "DeploymentType": {
      "Description": "The deployment type.",
      "Type": "String",
      "AllowedValues": ["Development", "Production"],
      "Default": "Development"
    },
    "VPC": {
      "Description": "The VPC for the EC2 instances.",
      "Type": "AWS::EC2::VPC::Id"
    },
    "Subnet1": {
      "Description": "The subnet1 for the EC2 instances.",
      "Type": "AWS::EC2::Subnet::Id"
    },
    "Subnet2": {
      "Description": "The subnet2 for the EC2 instances.",
      "Type": "AWS::EC2::Subnet::Id"
    },
    "SSHSecurityGroup": {
      "Description": "The SSH Security Group for the EC2 instances.",
      "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "KeyPair": {
      "Description": "The key pair name to use to connect to the EC2 instances.",
      "Type": "String"
    }
  },
  "Mappings": {
    "Globals": {
      "Constants": {
        "ImageId": "ami-0b898040803850657",
        "AssignPublicIP": "true",
        "WebInstanceSuffix": "web",
        "AppInstanceSuffix": "app"
      }
    },
    "DeploymentTypes": {
      "Development": {
        "InstanceType": "t2.small",
        "StorageSize": "20"
      },
      "Production": {
        "InstanceType": "t2.medium",
        "StorageSize": "50"
      }
    }
  },
  "Conditions": {
    "CreateMultipleInstances": {"Fn::Not": [{"Fn::Equals": ["Development", {"Ref": "DeploymentType"}]}]}
  },
  "Resources": {
    "LoadBalancer": {
      "Type": "AWS::ElasticLoadBalancing::LoadBalancer",
      "Condition": "CreateMultipleInstances",
      "Properties": {
        "Instances": [{"Ref": "Web1EC2Instance"}, {"Ref": "Web2EC2Instance"}],
        "Subnets": [{"Ref": "Subnet1"}, {"Ref": "Subnet2"}],
        "SecurityGroups": [{"Ref": "PublicWebSecurityGroup"}],
        "Listeners": [{
          "LoadBalancerPort": 80,
          "InstancePort": 80,
          "Protocol": "HTTP"
        }],
        "HealthCheck": {
          "Target": "HTTP:80/",
          "HealthyThreshold": "3",
          "UnhealthyThreshold": "5",
          "Interval": "10",
          "Timeout": "3"
        }
      },
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "fbf8f065-5dc7-4850-bb4f-8c4287a8cb7b"
        }
      }
    },
    "Web1EC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId": {"Fn::FindInMap": ["Globals", "Constants", "ImageId"]},
        "InstanceType": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "InstanceType"]},
        "NetworkInterfaces": [{
          "DeviceIndex": "0",
          "SubnetId": {"Ref": "Subnet1"},
          "AssociatePublicIpAddress": {"Fn::FindInMap": ["Globals", "Constants", "AssignPublicIP"]},
          "GroupSet": [{"Ref": "SSHSecurityGroup"}, {"Fn::If": ["CreateMultipleInstances", {"Ref": "PrivateWebSecurityGroup"}, {"Ref": "PublicWebSecurityGroup"}]}]
        }],
        "BlockDeviceMappings": [{
          "DeviceName": "/dev/sdm",
          "Ebs": {
            "VolumeType": "gp2",
            "VolumeSize": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "StorageSize"]},
            "DeleteOnTermination": "true"
          }
        }],
        "KeyName": {"Ref": "KeyPair"},
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, {"Fn::FindInMap": ["Globals", "Constants", "WebInstanceSuffix"]}, "1"]]}}],
        "UserData": {"Fn::Base64": {"Fn::Join": ["", [
          "#!/bin/bash\n",
          "yum install -y aws-cfn-bootstrap\n",
          "\n",
          "# Install the software\n",
          "/opt/aws/bin/cfn-init -v",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource Web1EC2Instance",
          " --configsets Install",
          " --region ", {"Ref": "AWS::Region"}, "\n",
          "\n",
          "# Signal resource creation completion\n",
          "/opt/aws/bin/cfn-signal -e $?",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource Web1EC2Instance",
          " --region ", {"Ref": "AWS::Region"}, "\n"
        ]]}}
      },
      "CreationPolicy": {
        "ResourceSignal": {
          "Count": 1,
          "Timeout": "PT5M"
        }
      },
      "DependsOn": "AppEC2Instance",
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "83fb66e0-bfdf-4076-9d59-3f1077f47a2a"
        },
        "AWS::CloudFormation::Init": {
          "configSets": {
            "Install": ["Install"]
          },
          "Install": {
            "packages": {
              "yum": {
                "httpd": []
              }
            },
            "files": {
              "/var/www/html/index.html": {
                "content": {"Fn::Join": ["", [
                  "&lt;html&gt;\n",
                  "  &lt;head&gt;\n",
                  "    &lt;title&gt;Welcome to a sample multi-tier app!&lt;/title&gt;\n",
                  "  &lt;/head&gt;\n",
                  "  &lt;body&gt;\n",
                  "    &lt;h1&gt;Welcome to a sample multi-tier app!&lt;/h1&gt;\n",
                  "  &lt;/body&gt;\n",
                  "&lt;/html&gt;\n"
                ]]},
                "mode": "0600",
                "owner": "apache",
                "group": "apache"
              }
            },
            "services": {
              "sysvinit": {
                "httpd": {"enabled": "true", "ensureRunning": "true"}
              }
            }
          }
        }
      }
    },
    "Web2EC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Condition": "CreateMultipleInstances",
      "Properties": {
        "ImageId": {"Fn::FindInMap": ["Globals", "Constants", "ImageId"]},
        "InstanceType": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "InstanceType"]},
        "NetworkInterfaces": [{
          "DeviceIndex": "0",
          "SubnetId": {"Ref": "Subnet2"},
          "AssociatePublicIpAddress": {"Fn::FindInMap": ["Globals", "Constants", "AssignPublicIP"]},
          "GroupSet": [{"Ref": "SSHSecurityGroup"}, {"Ref": "PrivateWebSecurityGroup"}]
        }],
        "BlockDeviceMappings": [{
          "DeviceName": "/dev/sdm",
          "Ebs": {
            "VolumeType": "gp2",
            "VolumeSize": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "StorageSize"]},
            "DeleteOnTermination": "true"
          }
        }],
        "KeyName": {"Ref": "KeyPair"},
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, {"Fn::FindInMap": ["Globals", "Constants", "WebInstanceSuffix"]}, "2"]]}}],
        "UserData": {"Fn::Base64": {"Fn::Join": ["", [
          "#!/bin/bash\n",
          "yum install -y aws-cfn-bootstrap\n",
          "\n",
          "# Install the software\n",
          "/opt/aws/bin/cfn-init -v",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource Web2EC2Instance",
          " --configsets Install",
          " --region ", {"Ref": "AWS::Region"}, "\n",
          "\n",
          "# Signal resource creation completion\n",
          "/opt/aws/bin/cfn-signal -e $?",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource Web2EC2Instance",
          " --region ", {"Ref": "AWS::Region"}, "\n"
        ]]}}
      },
      "CreationPolicy": {
        "ResourceSignal": {
          "Count": 1,
          "Timeout": "PT5M"
        }
      },
      "DependsOn": "AppEC2Instance",
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "4e1f2401-833d-442d-be04-89fac2d74778"
        },
        "AWS::CloudFormation::Init": {
          "configSets": {
            "Install": ["Install"]
          },
          "Install": {
            "packages": {
              "yum": {
                "httpd": []
              }
            },
            "files": {
              "/var/www/html/index.html": {
                "content": {"Fn::Join": ["", [
                  "&lt;html&gt;\n",
                  "  &lt;head&gt;\n",
                  "    &lt;title&gt;Welcome to a sample multi-tier app!&lt;/title&gt;\n",
                  "  &lt;/head&gt;\n",
                  "  &lt;body&gt;\n",
                  "    &lt;h1&gt;Welcome to a sample multi-tier app!&lt;/h1&gt;\n",
                  "  &lt;/body&gt;\n",
                  "&lt;/html&gt;\n"
                ]]},
                "mode": "0600",
                "owner": "apache",
                "group": "apache"
              }
            },
            "services": {
              "sysvinit": {
                "httpd": {"enabled": "true", "ensureRunning": "true"}
              }
            }
          }
        }
      }
    },
    "AppEC2Instance": {
      "Type": "AWS::EC2::Instance",
      "Properties": {
        "ImageId": {"Fn::FindInMap": ["Globals", "Constants", "ImageId"]},
        "InstanceType": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "InstanceType"]},
        "NetworkInterfaces": [{
          "DeviceIndex": "0",
          "SubnetId": {"Ref": "Subnet1"},
          "AssociatePublicIpAddress": {"Fn::FindInMap": ["Globals", "Constants", "AssignPublicIP"]},
          "GroupSet": [{"Ref": "SSHSecurityGroup"}, {"Ref": "AppSecurityGroup"}]
        }],
        "BlockDeviceMappings": [{
          "DeviceName": "/dev/sdm",
          "Ebs": {
            "VolumeType": "gp2",
            "VolumeSize": {"Fn::FindInMap": ["DeploymentTypes", {"Ref": "DeploymentType"}, "StorageSize"]},
            "DeleteOnTermination": "true"
          }
        }],
        "KeyName": {"Ref": "KeyPair"},
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, {"Fn::FindInMap": ["Globals", "Constants", "AppInstanceSuffix"]}, "1"]]}}],
        "UserData": {"Fn::Base64": {"Fn::Join": ["", [
          "#!/bin/bash\n",
          "yum install -y aws-cfn-bootstrap\n",
          "\n",
          "# Install the software\n",
          "/opt/aws/bin/cfn-init -v",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource AppEC2Instance",
          " --configsets Install",
          " --region ", {"Ref": "AWS::Region"}, "\n",
          "\n",
          "# Signal resource creation completion\n",
          "/opt/aws/bin/cfn-signal -e $?",
          " --stack ", {"Ref": "AWS::StackName"},
          " --resource AppEC2Instance",
          " --region ", {"Ref": "AWS::Region"}, "\n"
        ]]}}
      },
      "CreationPolicy": {
        "ResourceSignal": {
          "Count": 1,
          "Timeout": "PT5M"
        }
      },
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "4720705c-1add-4c63-abd6-d9fd4626a43d"
        },
        "AWS::CloudFormation::Init": {
          "configSets": {
            "Install": ["Install"]
          },
          "Install": {
            "packages": {
              "yum": {
                "tomcat": [],
                "tomcat-webapps": []
              }
            },
            "services": {
              "sysvinit": {
                "tomcat": {"enabled": "true", "ensureRunning": "true"}
              }
            }
          }
        }
      }
    },
    "PublicWebSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "public-web-sg"]]},
        "GroupDescription": {"Fn::Join": ["", ["Enables public web access for ", {"Ref": "AWS::StackName"}, "."]]},
        "VpcId": {"Ref": "VPC"},
        "SecurityGroupIngress": [
          {"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "CidrIp": "0.0.0.0/0"}
        ],
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "public-web-sg"]]}}]
      },
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "bfef096b-3b53-4799-b880-0df21011e7ed"
        }
      }
    },
    "PrivateWebSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "private-web-sg"]]},
        "GroupDescription": {"Fn::Join": ["", ["Enables private web access for ", {"Ref": "AWS::StackName"}, "."]]},
        "VpcId": {"Ref": "VPC"},
        "SecurityGroupIngress": [
          {"IpProtocol": "tcp", "FromPort": "80", "ToPort": "80", "SourceSecurityGroupId": {"Ref": "PublicWebSecurityGroup"}}
        ],
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "private-web-sg"]]}}]
      },
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "f00bae41-3fe2-41c1-ad14-64680744f71f"
        }
      }
    },
    "AppSecurityGroup": {
      "Type": "AWS::EC2::SecurityGroup",
      "Properties": {
        "GroupName": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "app-sg"]]},
        "GroupDescription": {"Fn::Join": ["", ["Enables access to ", {"Ref": "AWS::StackName"}, " app tier."]]},
        "VpcId": {"Ref": "VPC"},
        "SecurityGroupIngress": [
          {"IpProtocol": "tcp", "FromPort": "8080", "ToPort": "8080", "SourceSecurityGroupId": {"Fn::If": ["CreateMultipleInstances", {"Ref": "PrivateWebSecurityGroup"}, {"Ref": "PublicWebSecurityGroup"}]}}
        ],
        "Tags": [{"Key": "Name", "Value": {"Fn::Join": ["-", [{"Ref": "AWS::StackName"}, "app-sg"]]}}]
      },
      "Metadata": {
        "AWS::CloudFormation::Designer": {
          "id": "adf9b8b7-25c4-4ddb-9401-e5c34da55511"
        }
      }
    }
  },
  "Outputs": {
    "StackURL": {
      "Description": "The stack web URL.",
      "Value": {"Fn::Join": ["", ["http://",
          {"Fn::If": ["CreateMultipleInstances", {"Fn::GetAtt": ["LoadBalancer", "DNSName"]}, {"Fn::GetAtt": ["Web1EC2Instance", "PublicIp"]}]}
      ]]}
    }
  },
  "Metadata": {
    "AWS::CloudFormation::Designer": {
      "fbf8f065-5dc7-4850-bb4f-8c4287a8cb7b": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 560,
          "y": 50
        },
        "z": 0,
        "embeds": [],
        "isassociatedwith": [
          "83fb66e0-bfdf-4076-9d59-3f1077f47a2a",
          "4e1f2401-833d-442d-be04-89fac2d74778",
          "bfef096b-3b53-4799-b880-0df21011e7ed"
        ]
      },
      "83fb66e0-bfdf-4076-9d59-3f1077f47a2a": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 470,
          "y": 150
        },
        "z": 0,
        "embeds": []
      },
      "4e1f2401-833d-442d-be04-89fac2d74778": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 650,
          "y": 150
        },
        "z": 0,
        "embeds": []
      },
      "bfef096b-3b53-4799-b880-0df21011e7ed": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 460,
          "y": 50
        },
        "z": 0,
        "embeds": []
      },
      "c4db756b-b07b-4324-be5f-6ed116047ed8": {
        "source": {
          "id": "fbf8f065-5dc7-4850-bb4f-8c4287a8cb7b"
        },
        "target": {
          "id": "bfef096b-3b53-4799-b880-0df21011e7ed"
        },
        "z": 11
      },
      "4720705c-1add-4c63-abd6-d9fd4626a43d": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 553,
          "y": 265
        },
        "z": 0,
        "embeds": []
      },
      "a60d3d35-5a1d-4a58-a2bd-6f5ffe94017a": {
        "source": {
          "id": "83fb66e0-bfdf-4076-9d59-3f1077f47a2a"
        },
        "target": {
          "id": "4720705c-1add-4c63-abd6-d9fd4626a43d"
        },
        "z": 11
      },
      "f00bae41-3fe2-41c1-ad14-64680744f71f": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 660,
          "y": 270
        },
        "z": 1,
        "embeds": []
      },
      "adf9b8b7-25c4-4ddb-9401-e5c34da55511": {
        "size": {
          "width": 60,
          "height": 60
        },
        "position": {
          "x": 540,
          "y": 360
        },
        "z": 1,
        "embeds": []
      },
      "5f28f4f3-edee-437e-856b-dda339912a82": {
        "source": {
          "id": "4720705c-1add-4c63-abd6-d9fd4626a43d"
        },
        "target": {
          "id": "adf9b8b7-25c4-4ddb-9401-e5c34da55511"
        },
        "z": 11
      }
    }
  }
}

</pre>
<p>Let&#8217;s break it down by section to understand it better.</p>
<h3>Template Parameters</h3>
<ul>
<li>The <span style="font-family: courier new, courier, monospace;">DeploymentType</span> parameter is used to determine the deployment model. Such logical parameters are extremely useful as compared to exposing the individual resource properties as parameters. Why? Firstly, these enable the CFN template designer to ensure that the deployments meet only the prescribed models. Secondly, these hide unnecessary complexities from the template users. Also, tomorrow if you add more resources or change configurations, the template users do not have to be bothered about these.</li>
<li>The next 3 parameters take the target VPC and subnet information. Note that because we are doing a Production deployment we do want to leverage from the high availability capabilities offered by AWS so that we can distribute our EC2 instances across multiple Availability Zones.</li>
<li>The <span style="font-family: courier new, courier, monospace;">SSHSecurityGroup</span> parameter is used to specify the Security Group that will be used to connect to the EC2 instances. Now, you could very well create a Security Group for SSH in this template itself. However, I wanted to demonstrate the use of a Security Group that has been created by the networking team for access control. For example, they may set up the SSH Security Group to only allow inbound traffic from the corporate network. So, as opposed to every application team coming up with their own SSH Security Group, here the organization has chosen to use the same SSH Security Group for consistency and ease of management. These considerations are quite important when you design CFN templates. You want to ensure you are not creating backdoors that could lead to a potential security breach.</li>
<li>The <span style="font-family: courier new, courier, monospace;">KeyPair</span> parameter specifies the SSH key pair name that will be used for connecting to the EC2 instances.</li>
</ul>
<h3>Mappings</h3>
<ul>
<li>The <span style="font-family: courier new, courier, monospace;">Globals</span> map defines constants to avoid hardcoding values all over the template. For example, instead of hardcoding the AMI ID everywhere, we can simply define it once here. Tomorrow, if we want to change it, we just have to update it in one place. Likewise, the other constants.</li>
<li>The <span style="font-family: courier new, courier, monospace;">DeploymentTypes</span> map specifies the resource properties for each deployment model. For example, a Development EC2 instance will use <span style="font-family: courier new, courier, monospace;">t2.small</span> instance type. Whereas, a Production EC2 instance will use <span style="font-family: courier new, courier, monospace;">t2.medium</span>.</li>
</ul>
<h3>Conditions</h3>
<ul>
<li>The <span style="font-family: courier new, courier, monospace;">CreateMultipleInstances</span> condition is set to true only if it is NOT a Development deployment. This will be used later in the template when creating the resources. If you are wondering why I didn&#8217;t call it <span style="font-family: courier new, courier, monospace;">IsProductionDeployment</span>, there is a good reason. What if I add another deployment model tomorrow called <span style="font-family: courier new, courier, monospace;">QA</span>, which also has multiple instances? By keeping the condition name more generic, we can use it for both these deployment models.</li>
</ul>
<h3>Resources</h3>
<p>Notice the use of <span style="font-family: courier new, courier, monospace;">DependsOn</span> to ensure the resources are created in the correct order.</p>
<ul>
<li>First, it creates a load balancer (LB) for the web-tier if the <span style="font-family: courier new, courier, monospace;">CreateMultipleInstances</span> condition is true. This LB will have 2 EC2 instances attached &#8211; <span style="font-family: courier new, courier, monospace;">Web1EC2Instance</span> and <span style="font-family: courier new, courier, monospace;">Web2EC2Instance</span>. It will have access to the specified subnets and will be assigned the <span style="font-family: courier new, courier, monospace;">PublicWebSecurityGroup</span>. The LB will listen on port <span style="font-family: courier new, courier, monospace;">80</span> (HTTP) and will forward traffic to port <span style="font-family: courier new, courier, monospace;">80</span> on the EC2 instances. As we know, LB works by checking the health of the underlying instances. In this case, it will access the base URL (<span style="font-family: courier new, courier, monospace;">/</span>) every <span style="font-family: courier new, courier, monospace;">10 seconds</span> with a timeout value of <span style="font-family: courier new, courier, monospace;">3 seconds</span>. If the health check fails <span style="font-family: courier new, courier, monospace;">5</span> consecutive times, the instance will be declared unhealthy. And, the check must succeed <span style="font-family: courier new, courier, monospace;">3</span> consecutive times to declare the instance as healthy.</li>
<li>Next, it creates the <span style="font-family: courier new, courier, monospace;">Web1EC2Instance</span>. It uses the <span style="font-family: courier new, courier, monospace;">Globals</span> map to find some property values like the AMI ID. The <span style="font-family: courier new, courier, monospace;">InstanceType</span> is set based on the <span style="font-family: courier new, courier, monospace;">DeploymentType</span>. If it is a Production EC2 instance, it will be assigned the <span style="font-family: courier new, courier, monospace;">PrivateWebSecurityGroup</span> to avoid direct public access. For Development, it will be assigned the <span style="font-family: courier new, courier, monospace;">PublicWebSecurityGroup</span>. Also, the SSH Security Group will be assigned. The instance will have a single EBS volume attached. Apart from <span style="font-family: courier new, courier, monospace;">KeyName</span> and <span style="font-family: courier new, courier, monospace;">Tags</span>, notice the use of <span style="font-family: courier new, courier, monospace;">UserData</span>. This is used to install and configure the apache daemon when the instance first boots using the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html" target="_blank" rel="nofollow noopener noreferrer">AWS CFN Helper Scripts</a>. The <span style="font-family: courier new, courier, monospace;">Metadata</span> section contains the information used by these scripts to do their work. The <span style="font-family: courier new, courier, monospace;">CreationPolicy</span> is used to ensure that CFN waits till it receives a success or failure signal from the <span style="font-family: courier new, courier, monospace;">UserData</span> script with a timeout of <span style="font-family: courier new, courier, monospace;">5 minutes</span>. Note that <span style="font-family: courier new, courier, monospace;">Web1EC2Instance</span> is created regardless of the <span style="font-family: courier new, courier, monospace;">DeploymentType</span> since the stack will have at least one web-tier instance.</li>
<li>The <span style="font-family: courier new, courier, monospace;">Web2EC2Instance</span> is created only if the <span style="font-family: courier new, courier, monospace;">CreateMultipleInstances</span> condition is set to true. Its configuration is the same as the <span style="font-family: courier new, courier, monospace;">Web1EC2Instance</span>.</li>
<li>The <span style="font-family: courier new, courier, monospace;">AppEC2Instance</span> is created similarly with the key difference being it will be assigned the <span style="font-family: courier new, courier, monospace;">AppSecurityGroup</span> and tomcat will be installed on it. Note that just like the web-tier we could create multiple EC2 instances for the app-tier and put an LB in-front of these for high availability and load balancing purposes. But, I&#8217;ve skipped that part here for brevity purposes.</li>
<li>Next, it creates the Security Groups for the respective tiers. Notice how the <span style="font-family: courier new, courier, monospace;">PrivateWebSecurityGroup</span> sets its ingress rule to permit traffic only from the source resource that has the <span style="font-family: courier new, courier, monospace;">PublicWebSecurityGroup</span> assigned. This will ensure that only the LB can talk to the web EC2 instances.</li>
</ul>
<h3>Outputs</h3>
<ul>
<li>The template outputs the stack access URL. Again, it uses the <span style="font-family: courier new, courier, monospace;">CreateMultipleInstances</span> condition to determine whether the output URL should be based on the load balancer or the <span style="font-family: courier new, courier, monospace;">Web1EC2Instance</span>.</li>
</ul>
<h3>Metadata</h3>
<p>This section contains data used by the CFN Designer tool.</p>
<h2>Sample Deployment Commands</h2>
<p>The following command shows a Production deployment.</p>
<pre class="lang:default decode:true">aws cloudformation deploy --profile aws-training --stack-name MyAppProdStack --parameter-overrides DeploymentType=Production VPC=vpc-0ef286bd199748f2a Subnet1=subnet-05eaf962fd4e0e12c Subnet2=subnet-00077ede2ac0521a6 SSHSecurityGroup=sg-0fa7434cec1fd0b2d KeyPair=C9SSHKeyPair --template-file cfns/Multi_Tier_Stack.json</pre>
<p>And, here&#8217;s a command that shows a Development deployment.</p>
<pre class="lang:default decode:true">aws cloudformation deploy --profile aws-training --stack-name MyAppDevStack --parameter-overrides DeploymentType=Development VPC=vpc-0ef286bd199748f2a Subnet1=subnet-05eaf962fd4e0e12c Subnet2=subnet-00077ede2ac0521a6 SSHSecurityGroup=sg-0fa7434cec1fd0b2d KeyPair=C9SSHKeyPair --template-file cfns/Multi_Tier_Stack.json</pre>
<h2>Conclusion</h2>
<p>Great job in reading along. As you might have already gathered, authoring a good CFN template is no different from writing good code. It needs to have considerations of what you are trying to accomplish, enterprise readiness aspects like security and be cost-efficient. By thinking about these points upfront you can not only design a better template but also avoid common issues and save time in the longer run.</p>
<p>Happy deploying!<br />
&#8211; Nitin</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-a-multi-tier-stack-using-aws-cloudformation%2F&amp;linkname=How%20To%20Create%20A%20Multi-Tier%20Stack%20Using%20AWS%20CloudFormation" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-a-multi-tier-stack-using-aws-cloudformation%2F&amp;linkname=How%20To%20Create%20A%20Multi-Tier%20Stack%20Using%20AWS%20CloudFormation" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-a-multi-tier-stack-using-aws-cloudformation%2F&amp;linkname=How%20To%20Create%20A%20Multi-Tier%20Stack%20Using%20AWS%20CloudFormation" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-a-multi-tier-stack-using-aws-cloudformation%2F&amp;linkname=How%20To%20Create%20A%20Multi-Tier%20Stack%20Using%20AWS%20CloudFormation" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-a-multi-tier-stack-using-aws-cloudformation%2F&#038;title=How%20To%20Create%20A%20Multi-Tier%20Stack%20Using%20AWS%20CloudFormation" data-a2a-url="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/" data-a2a-title="How To Create A Multi-Tier Stack Using AWS CloudFormation"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/">How To Create A Multi-Tier Stack Using AWS CloudFormation</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-a-multi-tier-stack-using-aws-cloudformation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4405</post-id>	</item>
		<item>
		<title>How To Troubleshoot AWS CloudFormation Errors</title>
		<link>https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/</link>
					<comments>https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Tue, 17 Dec 2019 11:25:51 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4297</guid>

					<description><![CDATA[<p>How To Troubleshoot AWS CloudFormation Errors? AWS CloudFormation (CFN) helps in automating deployments by delivering Infrastructure as a Code (IaaC). It offers several useful capabilities, like simple templates, support for a wide range of AWS services, dependency management, parallel deployments,&#8230;&#160;<a href="https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/">How To Troubleshoot AWS CloudFormation Errors</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Troubleshoot AWS CloudFormation Errors?</h1>
<p>AWS CloudFormation (CFN) helps in automating deployments by delivering Infrastructure as a Code (IaaC). It offers several useful capabilities, like simple templates, support for a wide range of AWS services, dependency management, parallel deployments, and so on. To use CloudFormation, you create CFN templates either from scratch or from samples. You can also use tools like the CloudFormation Designer to author the CFN templates. However, similarly to coding, you will run into errors with CFN as well. In this post, we will cover the two prominent types of CFN errors and how to troubleshoot these.</p>
<h2>Types of CloudFormation Errors</h2>
<p>There are two types of CFN errors.</p>
<ol>
<li><strong>Syntax Errors</strong>: A CFN template is a text document in either JSON or YAML format. The syntax errors in the CFN template lead to this error. For example, a missing comma or brace in JSON, an incorrect indentation in YAML, and so on. Such a template is not even deployed as the CloudFormation Console or the CLI will fail upon detecting the error.</li>
<li><strong>Semantic Errors</strong>: These occur at deployment time typically due to coding or an infrastructure issue. For example, an incorrectly specified resource property name, trying to create a duplicate resource, and so on.</li>
</ol>
<h2>How To Troubleshoot CloudFormation Syntax Errors?</h2>
<p>Let&#8217;s take an example here. The following screenshot shows a CFN template snippet in JSON format.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?ssl=1"><img class="alignnone wp-image-4301 size-large" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=640%2C376&#038;ssl=1" alt="" width="640" height="376" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=1024%2C602&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=300%2C176&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=768%2C451&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=320%2C188&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=640%2C376&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=360%2C212&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=720%2C423&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=1080%2C635&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?resize=800%2C470&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace.png?w=1247&amp;ssl=1 1247w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>As you can see, the curly brace for the <span style="font-family: courier new, courier, monospace;">PolicyDocument</span> property is missing. When we try to deploy this CFN template, we will see an error like the one shown below.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?ssl=1"><img class="alignnone wp-image-4300 size-large" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=640%2C200&#038;ssl=1" alt="" width="640" height="200" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=1024%2C320&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=300%2C94&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=768%2C240&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=320%2C100&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=640%2C200&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=360%2C113&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=720%2C225&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=1080%2C338&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?resize=800%2C250&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Syntax_Error_Missing_Brace_CLI_Output.png?w=1266&amp;ssl=1 1266w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>Here the JSON parser has detected a missing comma or a curly brace. After you add the missing brace, the error will be resolved. Errors like these are quite common during development. Here are some tips on how to resolve or minimize the occurrence of such errors.</p>
<ul>
<li>Check if your text editor supports block matching capabilities, like the powerful <a href="https://www.vim.org/" target="_blank" rel="nofollow noopener noreferrer">VI editor</a>. This can be used to find the matching brace, and if you find that it is not on the expected element you have found the problem area. Then you can keep drilling down till you find the problem. As a general practice, it is also a good idea to always specify the closing brace when opening a brace so that you do not miss it. This can really come in handy for large templates.</li>
<li>You can also use a JSON validator or beautifier. There are several available online. While in most cases the validator may not reveal any more useful information than what the CFN CLI output shows, the beautifier may be a bit helpful to visually inspect the template for any anomalies.</li>
</ul>
<h2>How To Troubleshoot CloudFormation Semantic Errors?</h2>
<p>The semantic errors can range from simple things like incorrect property names, missing resource names to infrastructure-related errors, such as duplicate infrastructure resource name. And, as we discussed earlier, these occur at the deployment time. So, it may increase your end-to-end resolution time. Let&#8217;s take the example wherein we are trying to deploy an S3 bucket using a CFN template but a bucket with the specified name already exists. The following screenshot shows the CFN CLI output.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?ssl=1"><img class="alignnone wp-image-4303 size-large" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=640%2C170&#038;ssl=1" alt="" width="640" height="170" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=1024%2C272&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=300%2C80&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=768%2C204&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=320%2C85&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=640%2C170&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=360%2C96&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=720%2C191&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=1080%2C287&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?resize=800%2C213&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Output.png?w=1264&amp;ssl=1 1264w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>As you can see, the CLI execution failed. However, unlike the syntax error, the details are not available in this output. So, to troubleshoot further, you can either go to the CloudFormation Console or run the command shown in the above output.</p>
<p><span style="font-family: courier new, courier, monospace;">aws cloudformation describe-stack-events &#8211;stack-name c9apps-demo-bucket1</span></p>
<p>This will show the stack events in reverse chronological order (most recent event first). Scroll through the list till you find the error cause as shown below.</p>
<p><a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?ssl=1"><img class="alignnone size-large wp-image-4304" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=640%2C389&#038;ssl=1" alt="" width="640" height="389" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=1024%2C623&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=300%2C182&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=768%2C467&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=320%2C195&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=640%2C389&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=360%2C219&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=720%2C438&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=1080%2C657&amp;ssl=1 1080w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?resize=800%2C487&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_CLI_Describe_Events.png?w=1266&amp;ssl=1 1266w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>It shows that a bucket named <span style="font-family: courier new, courier, monospace;">c9apps-demo-bucket</span> (which was the bucket name we specified when deploying the template) already exists in another stack. This approach can be particularly useful for DevOps pipelines to retrieve the error information.</p>
<p>The other option is to go to the CloudFormation Console and look into the stack events for the error cause as shown below.</p>
<p><a href="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_Console_Output.png?ssl=1"><img class="alignnone size-large wp-image-4302" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Troubleshoot_CFN_Errors/CFN_Semantic_Error_Existing_Resource_Console_Output.png?resize=640%2C378&#038;ssl=1" alt="" width="640" height="378" data-recalc-dims="1" /></a></p>
<p>As we can see, the console shows the same information.</p>
<p>While semantic errors is a broader category and it is difficult to have a silver bullet solution for every scenario, here are some general tips.</p>
<ul>
<li>Use the <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html" target="_blank" rel="nofollow noopener noreferrer">AWS Resource and Property Types Reference</a> document to check the resources types and properties.</li>
<li>Use unique resource identifier names in the CFN templates. In general, giving names based on purpose is a good idea. For example, instead of calling it <span style="font-family: courier new, courier, monospace;">EC2Instance1</span>, a better name would be <span style="font-family: courier new, courier, monospace;">WebTierInstance1</span>.</li>
<li>CloudFormation offers several <a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html" target="_blank" rel="nofollow noopener noreferrer">Intrinsic Functions</a> for common computing needs. Leverage from these to make more meaningful and unique resource names. For example, the <span style="font-family: courier new, courier, monospace;">Fn::Join</span> Intrinsic Function can be used to combine a list of strings.</li>
<li>Leverage from the lifecycle for choosing the resource names. For example, resources that are global in nature (such as IAM role) may not have the stack name as part of their names. Whereas, resources that are meant for a specific stack only can use the stack name to make their names unique.</li>
</ul>
<p>Troubleshooting CFN errors takes some practice. Also, at times the error messages may not be easy to understand. So, it is a good idea to familiarize yourself with these techniques so that you are better prepared when the issues occur.</p>
<p>Be a smart troubleshooter!<br />
&#8211; Nitin</p>
<p><em>If you liked this post, you will find my <a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/" target="_blank" rel="noopener noreferrer">AWS CloudFormation Deep Dive</a> course helpful that focuses on many such best practices, techniques and hands-on examples to use CloudFormation in real-world deployments.<br />
</em></p>
<p>&nbsp;</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-troubleshoot-aws-cloudformation-errors%2F&amp;linkname=How%20To%20Troubleshoot%20AWS%20CloudFormation%20Errors" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-troubleshoot-aws-cloudformation-errors%2F&amp;linkname=How%20To%20Troubleshoot%20AWS%20CloudFormation%20Errors" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-troubleshoot-aws-cloudformation-errors%2F&amp;linkname=How%20To%20Troubleshoot%20AWS%20CloudFormation%20Errors" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-troubleshoot-aws-cloudformation-errors%2F&amp;linkname=How%20To%20Troubleshoot%20AWS%20CloudFormation%20Errors" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-troubleshoot-aws-cloudformation-errors%2F&#038;title=How%20To%20Troubleshoot%20AWS%20CloudFormation%20Errors" data-a2a-url="https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/" data-a2a-title="How To Troubleshoot AWS CloudFormation Errors"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/">How To Troubleshoot AWS CloudFormation Errors</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/cloud-computing/how-to-troubleshoot-aws-cloudformation-errors/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4297</post-id>	</item>
		<item>
		<title>How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros</title>
		<link>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/</link>
					<comments>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Thu, 05 Dec 2019 12:13:12 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4338</guid>

					<description><![CDATA[<p>How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros? AWS CloudFormation (CFN) conditions are quite useful for purposes like conditionally create resources, conditionally set the resource properties, and so on. However, when you start getting into some advanced&#8230;&#160;<a href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/">How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros?</h1>
<p>AWS CloudFormation (CFN) conditions are quite useful for purposes like conditionally create resources, conditionally set the resource properties, and so on. However, when you start getting into some advanced scenarios, these may become a bit limited. For example, checking for the existence of a resource so that you create it only once. How do you handle such scenarios? Is there any way you can do this via CFN as opposed to using some alternatives? That is precisely the purpose of this article.</p>
<p>Note that this is an advanced CFN topic. If you are new to CFN, please check out the <a href="https://cloudnineapps.com/blogs/cloud-computing/aws-cloudformation-an-architects-best-friend/" target="_blank" rel="noopener noreferrer">AWS CloudFormation &#8211; An Architect&#8217;s Best Friend</a> to understand the basics first.</p>
<h2>What Does Creating A Dynamic Condition Expression Mean?</h2>
<p>Simply put, it means creating the expression text dynamically at the deployment time. Typically, the condition expression is <span style="text-decoration: underline;">static</span>. For example, take a look at the condition below that will evaluate to true if the <span style="font-family: courier new, courier, monospace;">CreateGlobalResourcesParam</span> parameter is set to <span style="font-family: courier new, courier, monospace;">&#8220;true&#8221;</span>.</p>
<pre class="lang:default decode:true">  "CreateGlobalResources": {"Fn::Equals", ["true", {"Ref": "CreateGlobalResourcesParam"}]}</pre>
<p>When creating a Dynamic Condition Expression, the expression text is prepared at the deployment time.</p>
<pre class="lang:default decode:true">"CreateGlobalResources": &lt;content to prepare the expression text dynamically&gt;</pre>
<h2>What Is The Need To Create A Dynamic Condition Expression?</h2>
<p>To understand the need, let&#8217;s take a simple use case. Let&#8217;s say you have a CFN template that creates a serverless stack. It comprises a lambda and associated resources. Since the user base is spread across the globe, the plan is to create a stack per target region. For this discussion, let&#8217;s use <span style="font-family: courier new, courier, monospace;">us-east-1</span> and <span style="font-family: courier new, courier, monospace;">us-west-1</span> AWS regions with <span style="font-family: courier new, courier, monospace;">us-east-1</span> being the primary region.</p>
<p>So far so good. Now, we know that lambda requires an execution IAM role so that it has access to the required AWS resources. And, there are going to be two lambda deployments (one per region). So, we have two options &#8211; either create a lambda role per stack or create a single IAM role (say, in the primary stack) that will be used by all subsequent stacks. Both options have their own merits. The former offers more autonomy to each stack, whereas the second option leverages from the lifecycle of resources and minimizes the sprawl of roles that serve the same purpose. Another advantage of the second option is if there were updates to the role, you only need to update the primary stack and all stacks will automatically get the updates, thus reducing the end-to-end rollout team. Also, there are <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html" target="_blank" rel="noopener noreferrer nofollow">limits to the number of IAM roles</a> you can create. Although, you may be able to request an increase. This is just one scenario. But, there could be similar other use cases where you are trying to reuse a global resource across stacks.</p>
<p>So, for this discussion let&#8217;s say that we do want to create the IAM role only once. Now, let&#8217;s talk about how to achieve this by creating a Dynamic Condition Expression.</p>
<h2>Using Macro To Create A Dynamic Condition Expression</h2>
<p>CFN offers a powerful capability called <strong>Macro</strong>. If you have ever programmed in a language like C/C++ (or another language that supports pre-processors), you may be already familiar with the use of macros. Essentially, a CFN Macro lets you execute certain logic to modify either the content of the template or a snippet within the template. All macros are evaluated <span style="text-decoration: underline;">before</span> executing the CFN template. So, these are perfect to inject the condition expression dynamically. The following screenshot demonstrates this.</p>
<p><a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?ssl=1"><img class="alignnone size-large wp-image-4379" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=640%2C164&#038;ssl=1" alt="" width="640" height="164" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=1024%2C263&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=300%2C77&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=768%2C197&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=320%2C82&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=640%2C164&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=360%2C92&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=720%2C185&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=1080%2C277&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=800%2C205&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?resize=1280%2C328&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Dynamic_Condition_Expression_Sample.png?w=1294&amp;ssl=1 1294w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></p>
<p>Let&#8217;s understand this better.</p>
<ul>
<li>In the <strong>Conditions</strong> block, we are defining a condition named <span style="font-family: courier new, courier, monospace;">CreateGlobalResources</span>. It should be set to <span style="font-family: courier new, courier, monospace;">true</span> if the global resources should be created. Otherwise, it should be set to <span style="font-family: courier new, courier, monospace;">false</span>.</li>
<li>It is using the <span style="font-family: courier new, courier, monospace;">Fn::Transform</span> intrinsic function to invoke the <span style="font-family: courier new, courier, monospace;">ResourceHelper</span> macro with 2 parameters &#8211; <span style="font-family: courier new, courier, monospace;">Operation</span> and <span style="font-family: courier new, courier, monospace;">RoleName</span>. We will see the details of the macro later in this post. The <span style="font-family: courier new, courier, monospace;">Operation</span> parameter specifies the operation to perform (in this case, <span style="font-family: courier new, courier, monospace;">roleExists</span>, which will check for the existence of the specified role). The <span style="font-family: courier new, courier, monospace;">RoleName</span> parameter specifies the name of the role to check.</li>
<li>Here, the macro is expected to return the string <span style="font-family: courier new, courier, monospace;">&#8220;true&#8221;</span> only if the role exists. Otherwise, it should return the string <span style="font-family: courier new, courier, monospace;">&#8220;false&#8221;</span>. This value is then compared with <span style="font-family: courier new, courier, monospace;">&#8220;false&#8221;</span> using the <span style="font-family: courier new, courier, monospace;">Fn::Equals</span> intrinsic function.</li>
<li>This condition will be then used later in the template to conditionally create the <span style="font-family: courier new, courier, monospace;">LambdaFunctionRole</span> role as shown below.<br />
<a href="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?ssl=1"><img class="alignnone size-large wp-image-4352" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=640%2C338&#038;ssl=1" alt="" width="640" height="338" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=1024%2C541&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=300%2C158&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=768%2C406&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=320%2C169&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=640%2C338&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=360%2C190&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=720%2C380&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=1080%2C571&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=800%2C423&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?resize=1280%2C676&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Condition_Usage_Example.png?w=1310&amp;ssl=1 1310w" sizes="(max-width: 640px) 100vw, 640px" data-recalc-dims="1" /></a></li>
</ul>
<p>The idea here is when the primary stack is deployed in <span style="font-family: courier new, courier, monospace;">us-east-1</span>, the macro will return <span style="font-family: courier new, courier, monospace;">&#8220;false&#8221;</span> as the <span style="font-family: courier new, courier, monospace;">LambdaFunctionRole</span> role does not exist yet. Hence, the <span style="font-family: courier new, courier, monospace;">CreateGlobalResources</span> condition will be set to <span style="font-family: courier new, courier, monospace;">true</span> and the <span style="font-family: courier new, courier, monospace;">LambdaFunctionRole</span> will be created. When the stack is deployed in <span style="font-family: courier new, courier, monospace;">us-west-1</span>, the macro will return <span style="font-family: courier new, courier, monospace;">&#8220;true&#8221;</span> and the <span style="font-family: courier new, courier, monospace;">CreateGlobalResources</span> condition will be set to <span style="font-family: courier new, courier, monospace;">false</span>. Hence, the role will not be created again.</p>
<h2>Let&#8217;s See The Macro Code</h2>
<p>Now that we understand how the Dynamic Condition Expression is created, let&#8217;s take a look at the macro code.</p>
<pre class="lang:default decode:true">{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "A stack to provide utility methods for resources.",
  "Parameters": {
    "CreateLambdaRole": {
      "Description": "Whether to create the lambda role.",
      "Type": "String",
      "AllowedValues": ["true", "false"],
      "Default": "true"
    }
  },
  "Conditions": {
    "CreateGlobalResources": {"Fn::Equals": ["true", {"Ref": "CreateLambdaRole"}]}
  },
  "Resources": {
    "ResourceHelper": {
      "Type": "AWS::CloudFormation::Macro",
      "Properties": {
        "Name": {"Ref": "AWS::StackName"},
        "Description": "A macro to provide utility methods for resources.",
        "FunctionName": {"Fn::GetAtt": ["ResourceHelperLambda", "Arn"]}
      }
    },
    "ResourceHelperLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "FunctionName": "ResourceHelperLambda",
        "Handler": "index.handler",
        "Runtime": "nodejs8.10",
        "Role": {"Fn::Join": ["", ["arn:aws:iam::", {"Ref": "AWS::AccountId"}, ":role/ResourceHelperLambdaRole"]]},
        "MemorySize": "128",
        "Timeout": "30",
        "Code": {
          "ZipFile": {"Fn::Join": ["", [
            "const AWS = require('aws-sdk');\n",
            "AWS.config.update({region: '", {"Ref": "AWS::Region"}, "'});\n",
            "const iam = new AWS.IAM();\n",
            "\n",
            "exports.handler = (event, context, callback) =&gt; {\n",
            "  console.log('handler(): event: ' + JSON.stringify(event));\n",
            "  const params = event.params;\n",
            "  const op = params.Operation;\n",
			" const roleName = params.RoleName;\n",
            "  if (op == 'roleExists') {\n",
            "    var request = {\n",
            "      RoleName: roleName\n",
            "    };\n",
            "    iam.waitFor('roleExists', request, function(err, data) {\n",
            "      if (err) {\n",
            "        // Role does not exist\n",
            "        handleResponse(null, 'true');\n",
            "      }\n",
            "      else if (data.Role) {\n",
            "        // Role exists\n",
            "        handleResponse(null, 'false');\n",
            "      }\n",
            "      else {\n",
            "        handleResponse(new Error(`Could not get information about role '${params.RoleName}'.`), null);\n",
            "      }\n",
            "    });\n",
            "  }\n",
            "  else {\n",
            "    handleResponse(new Error(`Unsupported operation '${Operation}'.`), null);\n",
            "  }\n",
            "  const handleResponse = function(err, data) {\n",
            "    var response = {\n",
            "      status: 'SUCCESS',\n",
            "      requestId: event.requestId,\n",
            "    };\n",
            "    if (err) {\n",
            "      console.log('handleResponse(): ' + err);\n",
            "      response.status = 'FAILURE';\n",
            "    }\n",
            "    else {\n",
            "      response.fragment = data;\n",
            "    }\n",
            "    console.log('handleResponse(): response: ' + JSON.stringify(response));\n",
            "    callback(null, response);\n",
            "  };\n",
            "}\n"
          ]]}
        }
      }
    },
    "ResourceHelperLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Condition": "CreateGlobalResources",
      "Properties": {
        "RoleName": "ResourceHelperLambdaRole",
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [{
            "Effect": "Allow",
            "Principal": {
              "Service": "lambda.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
          }]
        },
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
          "arn:aws:iam::aws:policy/IAMReadOnlyAccess"
        ]
      }
    },
    "ResourceHelperLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {"Fn::Join": ["", ["/aws/lambda/", {"Ref": "ResourceHelperLambda"}]]},
        "RetentionInDays": 1
      }
    }
  }
}

</pre>
<p>As we know, the purpose of this macro is to prepare the Dynamic Condition Expression text with value as either <span style="font-family: courier new, courier, monospace;">&#8220;true&#8221;</span> (if the role exists) or <span style="font-family: courier new, courier, monospace;">&#8220;false&#8221;</span>. A macro is essentially a lambda-based stack that exists in the same region as the consuming stack. Here, I am using Node.js for implementation. If you are not familiar with it, do not worry. I will explain the important aspects below.</p>
<ul>
<li>The macro CFN template takes a single parameter &#8211; <span style="font-family: courier new, courier, monospace;">CreateLambdaRole</span>. It is referred by the <span style="font-family: courier new, courier, monospace;">CreateGlobalResources</span> condition that is used to conditionally create the IAM role required for the macro lambda. Do not confuse this with the use case we saw earlier. The condition here is strictly for the macro lambda role only. Can you guess why? Perhaps you got it. Since there are 2 AWS regions in our sample deployment, we will have 2 deployments of the macro stack as well. But, we would create the IAM role for the macro lambda only once and use it for both the stacks. So, when the macro stack is created in the primary region (<span style="font-family: courier new, courier, monospace;">us-east-1</span>), the <span style="font-family: courier new, courier, monospace;">CreateLambdaRole</span> parameter will be set to <span style="font-family: courier new, courier, monospace;">&#8220;true&#8221;</span> and the macro lambda role will be created. And, vice-versa for <span style="font-family: courier new, courier, monospace;">us-west-1</span>.</li>
<li>The first resource is the <span style="font-family: courier new, courier, monospace;">ResourceHelper</span> macro itself.</li>
<li>The next resource is the <span style="font-family: courier new, courier, monospace;">ResourceHelperLambda</span> that provides macro implementation.
<ul>
<li>In its <span style="font-family: courier new, courier, monospace;">Code</span> block, the AWS SDK is initialized first.</li>
<li>Next in the <span style="font-family: courier new, courier, monospace;">handler</span> function, we are first extracting the <span style="font-family: courier new, courier, monospace;">Operation</span> and <span style="font-family: courier new, courier, monospace;">RoleName</span> parameters. Apart from these parameters, the macro also receives other request data in a well-defined format, such as the <span style="font-family: courier new, courier, monospace;">requestId</span>, which is a unique identifier for a given macro call. The following screenshot shows a sample macro request.<br />
<a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?ssl=1"><img class="alignnone wp-image-4384 size-medium" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=300%2C145&#038;ssl=1" alt="" width="300" height="145" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=300%2C145&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=768%2C371&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=320%2C155&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=640%2C309&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=360%2C174&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=720%2C348&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?resize=800%2C386&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Request.png?w=816&amp;ssl=1 816w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></li>
<li>This is followed by a check to confirm if the request operation is <span style="font-family: courier new, courier, monospace;">roleExists</span>. If so, an IAM SDK call is issued to check whether the supplied role already exists.</li>
<li>If the role exists, a string with value <span style="font-family: courier new, courier, monospace;">&#8216;true&#8217;</span> is returned. Otherwise, <span style="font-family: courier new, courier, monospace;">&#8216;false&#8217;</span> is returned. This string output is then used to prepare the lambda response in a well-defined format, which includes additional fields, such as <span style="font-family: courier new, courier, monospace;">status</span>. The following screenshot shows a sample macro response. The content of the fragment field is our Dynamic Condition Expression text.<br />
<a href="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?ssl=1"><img class="alignnone wp-image-4382 size-medium" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=300%2C62&#038;ssl=1" alt="" width="300" height="62" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=300%2C62&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=768%2C159&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=320%2C66&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=640%2C132&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=360%2C74&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=720%2C149&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?resize=800%2C165&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/CloudComputing/How_To_Create_Dynamic_Expressions_In_AWS_CloudFormation_Using_Macros/Macro_Sample_Response.png?w=822&amp;ssl=1 822w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></li>
<li>The <span style="font-family: courier new, courier, monospace;">ResourceHelperLambdaRole</span> is the IAM role used by the macro lambda.</li>
<li>Finally, the <span style="font-family: courier new, courier, monospace;">ResourceHelperLambdaLogGroup</span> is the log group used by the macro lambda.</li>
</ul>
</li>
</ul>
<p>In this article, we saw how to use macros to create CFN condition expressions dynamically. This capability can be extremely useful, especially if you are trying to avoid splitting provisioning logic in multiple places, such as some in CFN and some via scripts. If you have multiple such common methods, you could create one or more reusable macros that can be used by multiple stacks thus increasing the reusability. So, next time you have a situation where you would want the CFN conditions to be dynamic, you may want to consider creating Dynamic Condition Expressions using macros.</p>
<p>Happy coding!<br />
&#8211; Nitin</p>
<p><em>If you liked this post, you will find my <a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/" target="_blank" rel="noopener noreferrer">AWS CloudFormation Deep Dive</a> course useful that focuses on many such best practices, techniques and hands-on examples to use CloudFormation in real-world deployments.<br />
</em></p>
<p>&nbsp;</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros%2F&amp;linkname=How%20To%20Create%20Dynamic%20Condition%20Expressions%20In%20AWS%20CloudFormation%20Using%20Macros" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros%2F&amp;linkname=How%20To%20Create%20Dynamic%20Condition%20Expressions%20In%20AWS%20CloudFormation%20Using%20Macros" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros%2F&amp;linkname=How%20To%20Create%20Dynamic%20Condition%20Expressions%20In%20AWS%20CloudFormation%20Using%20Macros" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros%2F&amp;linkname=How%20To%20Create%20Dynamic%20Condition%20Expressions%20In%20AWS%20CloudFormation%20Using%20Macros" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros%2F&#038;title=How%20To%20Create%20Dynamic%20Condition%20Expressions%20In%20AWS%20CloudFormation%20Using%20Macros" data-a2a-url="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/" data-a2a-title="How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/">How To Create Dynamic Condition Expressions In AWS CloudFormation Using Macros</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/cloud-computing/how-to-create-dynamic-condition-expressions-in-aws-cloudformation-using-macros/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4338</post-id>	</item>
		<item>
		<title>Best Smart Home Solutions</title>
		<link>https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/</link>
					<comments>https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Wed, 20 Nov 2019 11:58:35 +0000</pubDate>
				<category><![CDATA[Smart Home]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4065</guid>

					<description><![CDATA[<p>Best Smart Home Solutions Smart Home solutions are becoming increasingly popular, especially with the continuous value they add to our routine. On top of that, many of these are becoming simpler to implement with the time and these does not&#8230;&#160;<a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/">Best Smart Home Solutions</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Best Smart Home Solutions</h1>
<p>Smart Home solutions are becoming increasingly popular, especially with the continuous value they add to our routine. On top of that, many of these are becoming simpler to implement with the time and these does not need a lot of expertise. Always remember the key to have a successful smart home is to look for solutions that add value to your routine and lifestyle. In this post, I will cover some of the favorites that I consider to be the best Smart Home solutions. These are also sometimes referred by other names, such as smarthouse, intelligent home, homesmart, house control, automation system, and so on. I will keep this post updated. So, feel free to bookmark and check occasionally for any updates.</p>
<h2>My Favorite Smart Home Solutions</h2>
<p>Following is the list in no particular order. Feel free to jump to the specific one that you are interested in.</p>
<ul>
<li><a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#use_smart_switches" rel="noopener noreferrer">Automate indoor lighting and devices using Smart Switches/Dimmers</a></li>
<li><a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#use_smart_locks" rel="noopener noreferrer">Automate lock/unlock the door using a Smart Lock</a></li>
<li><a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#use_smart_thermostats" rel="noopener noreferrer">Manage heating/cooling smartly and more efficiently using Smart Thermostats</a></li>
<li><a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#use_smart_outlets" rel="noopener noreferrer">Automate lighting and devices using Smart Outlets</a></li>
<li><a href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/#use_smart_voice_assistant" rel="noopener noreferrer">Use voice to perform simple home automation tasks like turn lights on/off using a Smart Voice Assistant like Alexa</a></li>
</ul>
<h3><a name="use_smart_switches"></a>Automate indoor lighting and devices using Smart Switches/Dimmers</h3>
<div class="alignleft"><a href="https://cloudnineapps.com/blogs/smart-home/z-wave-smart-switch-setup-with-smartthings-hub/" target="_blank" rel="noopener noreferrer"><img class="size-medium wp-image-3426" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/GE_Z-Wave_Switch.jpg?resize=171%2C300&#038;ssl=1" alt="" width="171" height="300" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/GE_Z-Wave_Switch.jpg?resize=171%2C300&amp;ssl=1 171w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/GE_Z-Wave_Switch.jpg?resize=154%2C270&amp;ssl=1 154w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/GE_Z-Wave_Switch.jpg?w=260&amp;ssl=1 260w" sizes="(max-width: 171px) 100vw, 171px" data-recalc-dims="1" /></a></div>
<p><strong>Key Benefits</strong></p>
<ul>
<li>Turn <strong>on/off remotely</strong>.</li>
<li>Turn on/off on an <strong>event</strong>, such as a sunset.</li>
<li>Turn on/off on a <strong>schedule</strong>, such as 9 PM on weekdays.</li>
<li>It can also be used as a <strong>regular switch</strong>. Yes, I do get this question asked from time to time. It means that you can turn it <strong>on/off manually</strong>.</li>
<li>It could be used in combination with other smart devices to make more useful scenarios, such as in the morning turn off the lights and start the coffee maker attached to the outlet.</li>
</ul>
<p><a href="https://cloudnineapps.com/blogs/smart-home/z-wave-smart-switch-setup-with-smartthings-hub/" target="_blank" rel="noopener noreferrer">Click here</a> to learn more.</p>
<div class="clear"> </div>
<p>&nbsp;</p>
<h3><a name="use_smart_locks"></a>Automate lock/unlock the door using a Smart Lock</h3>
<div class="alignright"><a href="https://cloudnineapps.com/blogs/smart-home/smart-lock-setup-with-smart-hub/" target="_blank" rel="noopener noreferrer"><img class="alignnone size-medium wp-image-3415" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=300%2C200&#038;ssl=1" alt="" width="300" height="200" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=300%2C200&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=768%2C512&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=1024%2C682&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=320%2C213&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=640%2C426&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=360%2C240&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=720%2C480&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?resize=800%2C533&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Schlage_Smart_Lock.jpg?w=1037&amp;ssl=1 1037w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></div>
<p><strong>Key Benefits</strong></p>
<ul>
<li><strong>Keypad</strong> support: Several smart locks now offer keypads to enter the unlock key and to program keys.</li>
<li><strong>Programmable keys</strong>: A smart lock allows setting up multiple keys. For example, depending on your needs you can set up a key for each family member and for anyone who regularly visits home. The advantage of a key per user is you can track which key was used to unlock. Not everyone may need a key for every single user. But, you would at least want different keys for family members versus other people coming into the home regularly. In any case, it is good to know that such a capability is available if need be.</li>
<li><strong>Open/close lock remotely</strong>: This capability is precisely what it says. You do not need to be on your home network to lock/unlock the door remotely.</li>
<li>Open/lock with a key like a <strong>regular key</strong>. This is useful for regular access or in case the lock battery dies.</li>
</ul>
<p><a href="https://cloudnineapps.com/blogs/smart-home/smart-lock-setup-with-smart-hub/" target="_blank" rel="noopener noreferrer">Click here</a> to learn more.</p>
<p>&nbsp;</p>
<h3><a name="use_smart_thermostats"></a>Manage heating/cooling smartly and more efficiently using Smart Thermostats</h3>
<div class="alignleft"><a href="https://cloudnineapps.com/blogs/smart-home/smart-thermostat-setup-and-smartthings-integration/" target="_blank" rel="noopener noreferrer"><img class="alignnone size-medium wp-image-3419" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=300%2C225&#038;ssl=1" alt="" width="300" height="225" srcset="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=300%2C225&amp;ssl=1 300w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=768%2C576&amp;ssl=1 768w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=1024%2C768&amp;ssl=1 1024w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=320%2C240&amp;ssl=1 320w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=640%2C480&amp;ssl=1 640w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=360%2C270&amp;ssl=1 360w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=720%2C540&amp;ssl=1 720w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=1080%2C810&amp;ssl=1 1080w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=800%2C600&amp;ssl=1 800w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?resize=1280%2C960&amp;ssl=1 1280w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?w=1790&amp;ssl=1 1790w, https://i1.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Ecobee_Thermostat_With_Wall_Plate.jpeg?w=2685&amp;ssl=1 2685w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></div>
<p><strong>Key Benefits</strong></p>
<ul>
<li>Automatic <strong>presence detection</strong> and switching to/from the <strong>energy-saving</strong> mode.</li>
<li><strong>Schedule-based settings</strong> (such as different settings for sleep versus during the day).</li>
<li>It can easily be <strong>integrated with a smart hub</strong> to perform more intelligent functions. For example, when you depart home, you can trigger a routine or a scenario that locks the doors and puts the thermostat in the Away mode.</li>
<li>Traditional thermostat capabilities, such as changing the temperature on the fly, turning the fan on/off, turning the heat on/off, etc.</li>
</ul>
<p><a href="https://cloudnineapps.com/blogs/smart-home/smart-thermostat-setup-and-smartthings-integration/" target="_blank" rel="noopener noreferrer">Click here</a> to learn more.</p>
<p>&nbsp;</p>
<h3><a name="use_smart_outlets"></a>Automate lighting and devices using Smart Outlets</h3>
<div class="alignright"><a href="https://cloudnineapps.com/blogs/smart-home/z-wave-smart-outlet-setup-with-smartthings-hub/" target="_blank" rel="noopener noreferrer"><img class="alignnone size-medium wp-image-2531" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=210%2C300&#038;ssl=1" alt="SmartThings Outlet" width="210" height="300" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=210%2C300&amp;ssl=1 210w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=320%2C458&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=360%2C515&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=189%2C270&amp;ssl=1 189w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?resize=300%2C429&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Outlets/SmartThings_Outlet.jpeg?w=397&amp;ssl=1 397w" sizes="(max-width: 210px) 100vw, 210px" data-recalc-dims="1" /></a></div>
<p><strong>Key Benefits</strong></p>
<ul>
<li>Turn <strong>on/off remotely</strong>.</li>
<li>Turn on/off on an <strong>event</strong>, such as a sunset.</li>
<li>Turn on/off on a <strong>schedule</strong>, such as 7 AM on weekdays.</li>
<li>It could be used in combination with other smart devices to make more useful scenarios, such as in the morning turn off the lights and start the coffee maker attached to the outlet.</li>
</ul>
<p><a href="https://cloudnineapps.com/blogs/smart-home/z-wave-smart-outlet-setup-with-smartthings-hub/" target="_blank" rel="noopener noreferrer">Click here</a> to learn more.</p>
<p>&nbsp;</p>
<h3><a name="use_smart_voice_assistant"></a>Use voice to perform simple home automation tasks like turn lights on/off using a Smart Voice Assistant like Amazon Echo</h3>
<div class="alignleft"><a href="https://cloudnineapps.com/blogs/smart-home/amazon-echo-overview-and-setup/" target="_blank" rel="noopener noreferrer"><img class="alignnone size-medium wp-image-3492" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=300%2C239&#038;ssl=1" alt="" width="300" height="239" srcset="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=300%2C239&amp;ssl=1 300w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=768%2C611&amp;ssl=1 768w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=1024%2C815&amp;ssl=1 1024w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=320%2C255&amp;ssl=1 320w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=640%2C509&amp;ssl=1 640w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=360%2C286&amp;ssl=1 360w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=720%2C573&amp;ssl=1 720w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=1080%2C859&amp;ssl=1 1080w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=800%2C636&amp;ssl=1 800w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=1280%2C1018&amp;ssl=1 1280w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?resize=339%2C270&amp;ssl=1 339w, https://i0.wp.com/cloudnineapps.com/wp-content/uploads/blogs/SmartHome/Smart_Devices/Amazon_Echo.jpeg?w=1790&amp;ssl=1 1790w" sizes="(max-width: 300px) 100vw, 300px" data-recalc-dims="1" /></a></div>
<p><strong>Key Benefits</strong></p>
<ul>
<li>A Smart Voice Assistant like Amazon Echo (or Alexa) can help in making a voice-enabled smart home to control typical devices like smart lights, switches, outlets, thermostats, cameras and so on.</li>
<li>It is a platform that continues to become better and offers a lot more capabilities. For example, Alexa offers several skills ranging from general knowledge, science to entertainment.</li>
<li>It can be used as a speaker.</li>
<li>It also supports audio out.</li>
<li>It can be paired with a Bluetooth speaker.</li>
</ul>
<p><a href="https://cloudnineapps.com/blogs/smart-home/amazon-echo-overview-and-setup/" target="_blank" rel="noopener noreferrer">Click here</a> to learn more.</p>
<p>Enjoy your smart home!<br />
&#8211; Nitin</p>
<p>&nbsp;</p>
<div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;">
<center>
<h4>Looking for Smart Home resources?</h4>
</center>
<div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim">
<p><a href="https://cloudnineapps.com/blogs/smart-home/smart-home-product-recommendations/"><img class="aligncenter size-thumbnail wp-image-1896" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Smart_Home/SmartHomeBeyondTheBuzz/Smart_Home_Pic.png?resize=110%2C110&#038;ssl=1" alt="" width="110" height="110" data-recalc-dims="1" /></a></p>
<center>Our <strong><a href="https://cloudnineapps.com/blogs/smart-home/smart-home-product-recommendations/">Smart Home Product Recommendations</a></strong> provide quick reviews and ratings of commonly used smart home devices and more.</center>
</div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim">
<p><a href="https://cloudnineapps.com/courses/smart-home/smart-home-beyond-the-buzz/"><img class="aligncenter size-full wp-image-2085" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/courses/Smart_Home/SmartHomeBeyondTheBuzz/Smart_Home_Beyond_The_Buzz_Cover_Thumbnail.png?resize=206%2C109&#038;ssl=1" alt="" width="206" height="109" data-recalc-dims="1" /></a></p>
<center>Interested in learning more about how to set up a Smart Home? Check out our <strong><a href="https://cloudnineapps.com/courses/smart-home/smart-home-beyond-the-buzz/" rel="noopener">Smart Home &#8211; Beyond The Buzz</a></strong> course.</center>
</div></div> </div></div></div>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fsmart-home%2Fbest-smart-home-solutions%2F&amp;linkname=Best%20Smart%20Home%20Solutions" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fsmart-home%2Fbest-smart-home-solutions%2F&amp;linkname=Best%20Smart%20Home%20Solutions" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fsmart-home%2Fbest-smart-home-solutions%2F&amp;linkname=Best%20Smart%20Home%20Solutions" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fsmart-home%2Fbest-smart-home-solutions%2F&amp;linkname=Best%20Smart%20Home%20Solutions" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fsmart-home%2Fbest-smart-home-solutions%2F&#038;title=Best%20Smart%20Home%20Solutions" data-a2a-url="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/" data-a2a-title="Best Smart Home Solutions"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/">Best Smart Home Solutions</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/smart-home/best-smart-home-solutions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4065</post-id>	</item>
		<item>
		<title>How To Design Applications For Cloud (SaaS)</title>
		<link>https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/</link>
					<comments>https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Wed, 06 Nov 2019 12:00:45 +0000</pubDate>
				<category><![CDATA[Cloud Computing]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4271</guid>

					<description><![CDATA[<p>How To Design Applications For Cloud (SaaS) Software as a Service (SaaS) has been a predominant model for many software vendors. It helps similarly delivering software as a Cloud vendor delivers infrastructure services. SaaS applications are often deployed on a&#8230;&#160;<a href="https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/">How To Design Applications For Cloud (SaaS)</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>How To Design Applications For Cloud (SaaS)</h1>
<p>Software as a Service (SaaS) has been a predominant model for many software vendors. It helps similarly delivering software as a Cloud vendor delivers infrastructure services. SaaS applications are often deployed on a public cloud, like Amazon Cloud (AWS), Microsoft Azure, Google Cloud and so on. However, at times the organization may choose to use their datacenter (a.k.a. private cloud) to host the SaaS application and leverage their investment in the infrastructure. When you are designing SaaS applications, it takes more than just deploying application bits to the Cloud. Taking proper design considerations can not only help you in accomplishing a good design, but it can also help you in reducing costs and manage your deployment more effectively. In this post, I will cover some key considerations and tips to design SaaS applications that I have found useful over the years.</p>
<h2>How Is Designing Applications For Cloud Different From On-premise Applications Design?</h2>
<p>That&#8217;s a valid question that many Architects face, especially in the early phases. There are certain subtle differences. Let&#8217;s look at some of these just to get the perspective.</p>
<ul>
<li><strong>Better Modularization</strong>: If you have a monolithic application with a huge footprint, it is perhaps wise to see if it can be broken into logical components that can be deployed separately. This not only improves modularity but helps you reduce the footprint of the application. Let&#8217;s say you have an application that uses background jobs to refresh data. You could segregate the core application and the background jobs as 2 (or more) components that can be deployed separately. This will reduce the footprint of the core application. So, you could potentially choose a smaller resource size. Also, depending on the needs, you can scale these two independently. So, if there is an increase in demand for background jobs, you can increase its capacity and likewise for the application tier. Since the resource size for each of these is small, scaling only the required tier/component will lead to an overall lower cost than more bulky resources for the monolith. Makes sense?</li>
<li><strong>Application is always up-to-date</strong>: This is a big shift for many on-premise applications. In the Cloud, customers typically expect the application to be always on the latest version. Now, if you think about it as an Architect it means you are not only able to update the application bits but also upgrade customer data with preferably no customer involvement. That is, it is completely transparent to them.</li>
</ul>
<p>These are just some of the differences. But, you get the point.</p>
<h2>Key Design Considerations for SaaS</h2>
<p>When you are designing an application for Cloud, you want to consider the following key points.</p>
<ul>
<li><strong>Choose appropriate Cloud services</strong>: Of course, you are deploying to Cloud. But, which services do you want to use? Are you simply going to use Infrastructure as a Service (IaaS)? Or are you going to take advantage of some Platform as a Service (PaaS) capabilities as well? The answer may not be always straightforward. So, here are some guidelines.
<ul>
<li>Are you going to have the same application deployed to multiple Cloud platforms or on-premise as well? In that case, it may make sense to not have (or minimize) Cloud vendor-specific services and stick to more of IaaS services.</li>
<li>Cost should be an important consideration in choosing the services. For example, certain PaaS services that are Cloud vendor managed may be managed by your team itself to reduce cost. While this may not make sense for every service, it is worth exploring.</li>
<li>Keep your team expertise in mind. What would it take to use a certain Cloud service? And, if the team were to also maintain the underlying infrastructure, what skills would be needed?</li>
</ul>
</li>
<li><strong>Design for failure</strong>: Designing fault-tolerant and highly available applications is fundamental to Cloud. Assume that your application will run into issues and how you will ensure that it continues to serve the users. These could be application failures or underlying infrastructure failures. There are a few useful capabilities offered by Cloud vendors to help here.
<ul>
<li><strong>Use a Load Balancer</strong>: You can put the application nodes behind a Load Balancer for both load-balancing purposes as well as to make sure that even if one or more nodes go down, the application is served via the other nodes.</li>
<li><strong>Geographically distributed application</strong>: Several Cloud vendors offer capabilities to spread the application across multiple geographical areas so that even if one area is impacted (say, due to a natural disaster), the application can be served from the other areas. For example, AWS supports deploying an application across multiple Availability Zones.</li>
</ul>
</li>
<li><strong>Modularize your application</strong>: As we discussed in the earlier section, segregating components that can be deployed and managed separately can help reduce the footprint of the application and thus reduce the cost of the infrastructure. You may also consider making some of these components as <strong>microservices</strong>. The microservice approach can be particularly useful if there are other potential consumers besides your application. Now, that does not mean, you go overboard and create unnecessary components. Hence, one way to do this is to make components that can be deployed separately (such as core application versus background jobs).</li>
<li><strong>Security</strong>: Security involves many aspects &#8211; from securing your infrastructure to application. Some of the key aspects include ensuring that only the required ports are opened, using as minimal privileges on the resources as possible, having proper role-based access control, use of encryption, and so on. Security should not be looked at as a one-time deal. It is an on-going process that should improve and evolve over time.</li>
<li><strong>Multi-tenancy</strong>: A key benefit of running in the Cloud is being able to serve multiple customers using the <span style="text-decoration: underline;">same</span> instance of the application. This brings out some obvious challenges in the application design to ensure that each customer&#8217;s data is segregated for both security and regulatory purposes. Some teams choose to go with a different persistent storage instance per customer, such as a separate database per customer. And, some choose to segregate data using row-level identifiers. Regardless of which approach you take, it is important to ensure that the architecture meets the scalability and security needs. For example, if you choose to go with a database per customer, you can host multiple databases on one RDS instance. And, when you run out of capacity, you can stand up another RDS instance.</li>
<li><strong>Zero/Minimal Downtime and Seamless Upgrades</strong>: Believe it or not, many customers expect that SaaS applications will have zero or very minimal downtime and since these are often managed by the same company who built the application, it should be upgraded seamlessly. The challenge is your application may not have been designed to handle upgrades smoothly, especially if it is a pre-existing application being converted to a SaaS application. There are 2 key aspects to consider a) deploying application bits and files b) handling persistent store upgrades. For rolling out application bits strategies like Blue/Green deployment can be used in which the new release is deployed to a new stack, tested and made live if the rollout was successful. The older stack resources can be decommissioned and reclaimed at a later point. One approach to achieve seamless upgrades is to make the underlying data model <strong>n &#8211; 1 compatible</strong>. What that means is if the release being deployed is of data model version <strong>n</strong>, it&#8217;s data model is backward compatible with the previous data model version (n &#8211; 1) thus ensuring that the upgrade will not break it. How can you ensure that? This requires incorporating discipline throughout your development cycle and following certain guidelines, like not deleting any columns, providing necessary upgrade scripts to handle any data migration needs, and so on. And, in the event upgrade is not successful, having support to <strong>rollback</strong> the upgrade. Now, you can understand this is not only technically challenging as this involves data migration and rollback, but it could also lead to a significantly slower rollout. Hence, you have to evaluate carefully what is reasonable for your application needs and implement the solution accordingly.</li>
<li><strong>Optimal Cost</strong>: As you progress through your application and deployment design, you would be able to come up with multiple approaches to deploy the same application. However, one key aspect to be successful in SaaS is to ensure that you choose the most cost-effective model that not only meets your immediate needs but can cater to at least the near future needs, such as when the demand rises or slows down. You do not want to be spending overtly, but not so less that the application starts choking with very few users. Hence, it is important to strike the right balance. A rule of thumb that I like to follow is when choosing resource sizing always go on the conservative side. And, if the testing reveals higher configuration is needed, then only increase.</li>
</ul>
<h2>DevOps Considerations For SaaS</h2>
<p>DevOps is so critical for SaaS that it is worth discussing it separately. The following are some key considerations.</p>
<ul>
<li><strong>Continuous Delivery</strong>: The DevOps pipelines should be able to take the checked-in code, produce a build from it that then passes through various stages (QA, performance, final go/no go checks, production deploy) in an <span style="text-decoration: underline;">automated</span> manner. This may involve having multiple pipelines (typically, per stage) and having an uber pipeline that pushes the build through each of these stages. Now, the pipelines may also take some time to develop, but it is a good idea to start defining the contracts for each pipeline so that the consumer pipelines do not need to worry about the details. Eventually, the goal should be to get completely hands-free or as close to it as possible.</li>
<li><strong>Use Version Control for everything including DevOps changes</strong>: For application code, it is generally well understood to use the master branch of the source control. However, it is equally important to do the same for any DevOps changes. For example, when you are rolling out infrastructure changes, these should also be checked into the source control, tested and then pushed to production.</li>
<li><strong>Agile Infrastructure</strong>: To be successful at SaaS, you want to make sure that your infrastructure is agile and can cope up with the changes in demand. As the demand goes up, it can scale appropriate tier and when the demand goes down release the non-required resources. This requires a certain level of experimentation and testing to get to the right balance. For example, you can use AWS auto-scaling capabilities to automatically scale up/down the infrastructure.</li>
<li><strong>Monitoring and Alerts</strong>: The stacks these days have multiple moving parts and troubleshooting could be a bit of a challenge. Hence, it is important to have the right monitoring and alerting mechanisms in place so that when things go wrong, you can troubleshoot the problem more quickly. It is a good idea to leverage from some of the core Cloud monitoring capabilities like centralized logging, alarms, and notifications on errors.</li>
</ul>
<h2>Other Considerations For SaaS</h2>
<ul>
<li><strong>Planning and Prioritization</strong>: Like any other successful project, SaaS projects also require planning and prioritization. While everyone wants to go for goals like &#8220;push every check in to production&#8221;, see what makes the most business sense and prioritize the important things first. Of course, having a stretch goal is not wrong. But, it is important to get the important things right first. For example, if you do not have a good unit testing and automation coverage and you are trying to push every code change to production, even if you accomplish it, the usefulness is questionable. It can backfire because things can start breaking too quickly in production and then the R&amp;D team will be consumed in handling those.</li>
<li><strong>Monetization Model</strong>: SaaS also impacts the monetization model. While in on-premise you may be fine selling license for a certain amount, in SaaS you may have to rethink what is the most suitable model for your business. Do you want to use a subscription-based model, utilization-based model, a hybrid model, or something else altogether?</li>
</ul>
<p>Hopefully, you got a better insight into what it takes to design a Cloud-based or SaaS application. It is certainly an enriching experience to see your application that involves so many different aspects, go live in production. As I always say, <em>&#8220;Cloud is a journey and not a destination&#8221;</em>. So, keep learning and evolving.</p>
<p>Happy designing!<br />
&#8211; Nitin</p>
<p><em>If you liked this post, you will find my <a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/" rel="noopener noreferrer">AWS Advanced For Developers</a> course helpful that focuses on many such best practices and techniques to design and deploy real-world applications in AWS.</em></p>
<p>&nbsp;</p>
<p><div class="su-note"  style="border-color:#e5d6d4;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"><div class="su-note-inner su-u-clearfix su-u-trim" style="background-color:#fff0ee;border-color:#ffffff;color:#333333;border-radius:5px;-moz-border-radius:5px;-webkit-border-radius:5px;"></p>
<center>
<h4>Enhance your AWS skills with these hands-on courses for real-world deployments.</h4>
</center>
<p><div class="su-row"> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-cloudformation-deep-dive/"><img class="aligncenter wp-image-3758 size-medium" src="https://i1.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_CloudFormation_Deep_Dive/AWS_CloudFormation_Deep_Dive_Logo.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn CloudFormation from concepts to hands-on examples.</center>
<p></div></div> <div class="su-column su-column-size-1-2"><div class="su-column-inner su-u-clearfix su-u-trim"></p>
<p><a href="https://cloudnineapps.com/courses/cloud-computing/aws-advanced-for-developers/"><img class="size-full wp-image-2068 aligncenter" src="https://i0.wp.com/cloudnineapps.com/wp-content/uploads/courses/Cloud_Computing/AWS_Advanced_For_Developers/AWS_Advanced_For_Developers_Logo_small.png?resize=192%2C108&#038;ssl=1" alt="" width="192" height="108" data-recalc-dims="1" /></a></p>
<center>Learn practical application development on AWS.</center>
<p></div></div> </div></div></div></p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-design-applications-for-cloud-saas%2F&amp;linkname=How%20To%20Design%20Applications%20For%20Cloud%20%28SaaS%29" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-design-applications-for-cloud-saas%2F&amp;linkname=How%20To%20Design%20Applications%20For%20Cloud%20%28SaaS%29" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-design-applications-for-cloud-saas%2F&amp;linkname=How%20To%20Design%20Applications%20For%20Cloud%20%28SaaS%29" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-design-applications-for-cloud-saas%2F&amp;linkname=How%20To%20Design%20Applications%20For%20Cloud%20%28SaaS%29" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fcloud-computing%2Fhow-to-design-applications-for-cloud-saas%2F&#038;title=How%20To%20Design%20Applications%20For%20Cloud%20%28SaaS%29" data-a2a-url="https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/" data-a2a-title="How To Design Applications For Cloud (SaaS)"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/">How To Design Applications For Cloud (SaaS)</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/cloud-computing/how-to-design-applications-for-cloud-saas/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4271</post-id>	</item>
		<item>
		<title>Shopping Guru 1.1.3 Available</title>
		<link>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/</link>
					<comments>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/#respond</comments>
		
		<dc:creator><![CDATA[Nitin Patil]]></dc:creator>
		<pubDate>Thu, 24 Oct 2019 14:24:27 +0000</pubDate>
				<category><![CDATA[Mobile]]></category>
		<guid isPermaLink="false">https://cloudnineapps.com/?p=4335</guid>

					<description><![CDATA[<p>Shopping Guru 1.1.3 Available Following are the highlights of this release. A simple periodic notification enhancement to remind about visiting the app to check for any price drops and managing the purchases. This will help in not missing out on&#8230;&#160;<a href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/" class="more-link">Read More</a></p>
<p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/">Shopping Guru 1.1.3 Available</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Shopping Guru 1.1.3 Available</h1>
<p><a href="https://cloudnineapps.com/products/mobile/shopping-guru/"><img class="wp-image-2666 size-thumbnail alignleft" src="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=150%2C150&#038;ssl=1" alt="" width="150" height="150" srcset="https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=150%2C150&amp;ssl=1 150w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=300%2C300&amp;ssl=1 300w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=768%2C768&amp;ssl=1 768w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=320%2C320&amp;ssl=1 320w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=640%2C640&amp;ssl=1 640w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=360%2C360&amp;ssl=1 360w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=720%2C720&amp;ssl=1 720w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=800%2C800&amp;ssl=1 800w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?w=1024&amp;ssl=1 1024w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=270%2C270&amp;ssl=1 270w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=200%2C200&amp;ssl=1 200w, https://i2.wp.com/cloudnineapps.com/wp-content/uploads/products/mobile/ShoppingGuru/ShoppingGuru_Logo_Circle.png?resize=100%2C100&amp;ssl=1 100w" sizes="(max-width: 150px) 100vw, 150px" data-recalc-dims="1" /></a>Following are the highlights of this release.</p>
<ul>
<li>A simple periodic notification enhancement to remind about visiting the app to check for any price drops and managing the purchases. This will help in not missing out on deals.</li>
<li>Other minor improvements and fixes</li>
</ul>
<p><a href="https://cloudnineapps.com/products/mobile/shopping-guru/">Check it out</a> now! We would love to hear your feedback.</p>
<p>&nbsp;</p>
<p><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-1-3-available%2F&amp;linkname=Shopping%20Guru%201.1.3%20Available" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-1-3-available%2F&amp;linkname=Shopping%20Guru%201.1.3%20Available" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-1-3-available%2F&amp;linkname=Shopping%20Guru%201.1.3%20Available" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_pinterest" href="https://www.addtoany.com/add_to/pinterest?linkurl=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-1-3-available%2F&amp;linkname=Shopping%20Guru%201.1.3%20Available" title="Pinterest" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd a2a_counter addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fcloudnineapps.com%2Fblogs%2Fmobile%2Fshopping-guru-1-1-3-available%2F&#038;title=Shopping%20Guru%201.1.3%20Available" data-a2a-url="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/" data-a2a-title="Shopping Guru 1.1.3 Available"></a></p><p>The post <a rel="nofollow" href="https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/">Shopping Guru 1.1.3 Available</a> appeared first on <a rel="nofollow" href="https://cloudnineapps.com">Cloud Nine Apps</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cloudnineapps.com/blogs/mobile/shopping-guru-1-1-3-available/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4335</post-id>	</item>
	</channel>
</rss>
