<?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/"
	>

<channel>
	<title>Engine Yard Blog</title>
	<atom:link href="https://www.engineyard.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.engineyard.com/blog/</link>
	<description>PaaS Platform as a Service &#124; PaaS Solution</description>
	<lastBuildDate>Thu, 30 Mar 2023 15:42:27 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://www.engineyard.com/wp-content/uploads/2021/10/cropped-favicon-32x32.png</url>
	<title>Engine Yard Blog</title>
	<link>https://www.engineyard.com/blog/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Engine Yard Cloud: Pricing Update</title>
		<link>https://www.engineyard.com/blog/engine-yard-cloud-pricing-update/</link>
		
		<dc:creator><![CDATA[Ravi Duddukuru]]></dc:creator>
		<pubDate>Thu, 02 Mar 2023 17:07:06 +0000</pubDate>
				<category><![CDATA[Application Deployment]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/?p=3762</guid>

					<description><![CDATA[<p>We are proud to be working with our customers while they continue to enjoy our Engine Yard products. Here are some changes we are making to Engine Yard Cloud pricing, as well as some opportunities for you to reduce your bill. Starting April 1st 2023 our prices will be changing. These changes enable us to [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-cloud-pricing-update/">Engine Yard Cloud: Pricing Update</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>We are proud to be working with our customers while they continue to enjoy our Engine Yard products. Here are some changes we are making to Engine Yard Cloud pricing, as well as some opportunities for you to reduce your bill.</p>



<p>Starting April 1<sup>st</sup> 2023 our prices will be changing. These changes enable us to reinvest back into the Engine Yard product ensuring that we provide our customers with best-in-class PaaS. It also takes into consideration inflation.</p>



<h3 class="has-medium-font-size wp-block-heading">Support Pricing</h3>



<p>These changes will be reflected in your invoice based on the date above, on the following billing cycle.</p>



<figure class="wp-block-table"><table><thead><tr><th class="has-text-align-left" data-align="left">Flex</th><th class="has-text-align-left" data-align="left">New Price Per Instance / Month*</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">Solo</td><td class="has-text-align-left" data-align="left">$50</td></tr><tr><td class="has-text-align-left" data-align="left">Standard</td><td class="has-text-align-left" data-align="left">$180</td></tr><tr><td class="has-text-align-left" data-align="left">Premium</td><td class="has-text-align-left" data-align="left">$360</td></tr><tr><td class="has-text-align-left" data-align="left">Platinum</td><td class="has-text-align-left" data-align="left">$450</td></tr></tbody></table></figure>



<div style="color:#ddd" class="wp-block-genesis-blocks-gb-spacer gb-block-spacer gb-divider-solid gb-divider-size-1"><hr style="height:12px"/></div>



<figure class="wp-block-table"><table><thead><tr><th class="has-text-align-left" data-align="left">TVP (m5.large example)</th><th class="has-text-align-left" data-align="left">New Price Per Instance/Hour*</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">Basic</td><td class="has-text-align-left" data-align="left">$0.087</td></tr><tr><td class="has-text-align-left" data-align="left">Standard</td><td class="has-text-align-left" data-align="left">$0.175</td></tr><tr><td class="has-text-align-left" data-align="left">Premium</td><td class="has-text-align-left" data-align="left">$0.262</td></tr><tr><td class="has-text-align-left" data-align="left">Platinum</td><td class="has-text-align-left" data-align="left">$0.366</td></tr></tbody></table></figure>



<p class="has-small-font-size">*Applies to Engine Yard Cloud base pricing. Additional charges for support on older stack versions remain.</p>



<p>Platinum pricing will <strong>not</strong> change in either offerings.</p>



<h3 class="has-medium-font-size wp-block-heading">Account Charges</h3>



<p>Engine Yard provides instances which require maintenance and monitoring irrespective of the level of resources customers use. In order to support this maintenance, we will need to add an Account Maintenance Fee that, up until now we have never charged.</p>



<figure class="wp-block-table"><table><thead><tr><th class="has-text-align-left" data-align="left">Maintenance</th><th class="has-text-align-left" data-align="left">Monthly**</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">Engine Yard Account Maintenance Fee</td><td class="has-text-align-left" data-align="left">$99.00</td></tr></tbody></table></figure>



<p class="has-small-font-size">**Applies to Engine Yard Cloud accounts.</p>



<p>Again, this will allow us to execute on our deliverables to our clients, both from a platform and support standpoint.</p>



<h3 class="has-medium-font-size wp-block-heading">Cost Savings on Annual Term</h3>



<p>Engine Yard is happy to announce a new agreement with AWS which is based on us working with them on an annual basis. As a thank you for being an Engine Yard customer, we would like to directly pass these savings on to you.</p>



<p>Therefore, we are offering the below discount on AWS IaaS instances moving forward:</p>



<figure class="wp-block-table"><table><thead><tr><th class="has-text-align-left" data-align="left">Term</th><th class="has-text-align-left" data-align="left">Discount (AWS IaaS instances)</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left">Annual</td><td class="has-text-align-left" data-align="left">10%</td></tr></tbody></table></figure>



<div style="color:#ddd" class="wp-block-genesis-blocks-gb-spacer gb-block-spacer gb-divider-solid gb-divider-size-1"><hr style="height:16px"/></div>



<p>In order to benefit from this discount please reach out to <a href="mailto:customersuccess@engineyard.com">customersuccess@engineyard.com</a> and they will be able to advise and update your invoice accordingly.</p>



<p>For any further information please reach out to <a href="mailto:customersuccess@engineyard.com">customersuccess@engineyard.com</a>.</p>



<p>We thank you for being a valued Engine Yard customer. We appreciate your business and look forward to continuing to help you be successful.</p>



<p><em>The Engine Yard Team</em></p>



<div style="color:#ddd" class="wp-block-genesis-blocks-gb-spacer gb-block-spacer gb-divider-solid gb-divider-size-1"><hr style="height:28px"/></div>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-cloud-pricing-update/">Engine Yard Cloud: Pricing Update</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Engine Yard stack v7 is now generally available</title>
		<link>https://www.engineyard.com/blog/engine-yard-stack-v7-is-now-generally-available/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Thu, 23 Jun 2022 16:34:19 +0000</pubDate>
				<category><![CDATA[Updates]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/?p=3689</guid>

					<description><![CDATA[<p>We are excited to announce the general availability of Engine Yard stack v7. The stack v7 brings the latest technology, databases and processors together so that you can run your applications faster and cheaper.  Latest Tech: Ruby: version 2.7 to 3.1 and support for future versions of Ruby Rails: versions 5,6, 7 and support for [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-stack-v7-is-now-generally-available/">Engine Yard stack v7 is now generally available</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="3689" class="elementor elementor-3689">
									<section class="elementor-section elementor-top-section elementor-element elementor-element-9f8bb4f elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="9f8bb4f" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2a44f23" data-id="2a44f23" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-1330694 elementor-widget elementor-widget-text-editor" data-id="1330694" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
			<style>/*! elementor - v3.11.2 - 22-02-2023 */
.elementor-widget-text-editor.elementor-drop-cap-view-stacked .elementor-drop-cap{background-color:#818a91;color:#fff}.elementor-widget-text-editor.elementor-drop-cap-view-framed .elementor-drop-cap{color:#818a91;border:3px solid;background-color:transparent}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap{margin-top:8px}.elementor-widget-text-editor:not(.elementor-drop-cap-view-default) .elementor-drop-cap-letter{width:1em;height:1em}.elementor-widget-text-editor .elementor-drop-cap{float:left;text-align:center;line-height:1;font-size:50px}.elementor-widget-text-editor .elementor-drop-cap-letter{display:inline-block}</style>				<p><span style="font-weight: 400;">We are excited to announce the general availability of Engine Yard stack v7. The stack v7 brings the latest technology, databases and processors together so that you can run your applications faster and cheaper. </span></p><p><strong><span style="text-decoration: underline;">Latest Tech:</span></strong></p><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Ruby: version 2.7 to 3.1 and support for future versions of Ruby</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Rails: versions 5,6, 7 and support for future versions of Rails</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">NodeJS: version 14+</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">PHP: versions 7.3+, version 8.0+</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">MySQL: v5.7, v8</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">PostgreSQL: v9.5 to v14+</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Operating System: Ubuntu v20.04 LTS and support for Ubuntu v22.04 LTS is coming soon</span></li></ul><p><i><span style="font-weight: 400;">OS EOL &#8211; </span></i><span style="font-weight: 400;">Stack v6 runs on Ubuntu 18.04 LTS and that is going to be EOL in just a few months (April, 2023). Older stacks such as v5 and v4 run OS versions that have already reached EOL. Stack v7 supports Ubuntu 20.04 LTS and it will soon support 22.04 LTS which will have a much longer life. That’s one more reason to upgrade your applications to stack v7 now.</span></p><p><span style="text-decoration: underline;"><strong>Graviton ARM Support</strong></span><span style="font-weight: 400;"><span style="text-decoration: underline;"><strong>:</strong></span> Graviton has been game changing for reducing AWS costs. Graviton2 delivers 40% price-performance over an equivalent x86 processor. Graviton3 provides up to 25% better compute performance compared to Graviton2 processors. With stack v7, Engine Yard now supports Graviton2 and Graviton3.</span></p><p><span style="text-decoration: underline;"><strong>V7 supports both x86 &amp; ARM</strong></span><span style="font-weight: 400;"><span style="text-decoration: underline;"><strong>:</strong></span> We realize that it’s not easy to migrate applications to ARM. That is why we built stack v7 to support both x86 and Graviton ARM instances so that you can spend less effort migrating your applications to Graviton. That’s one more way we make AWS Easy!</span></p><p><span style="text-decoration: underline;"><strong>Enhanced Support Plans</strong></span><span style="font-weight: 400;"><span style="text-decoration: underline;"><strong>:</strong></span> We recognize that taking advantage of these innovations requires extra effort. We want to ensure that you get the most support from Engine Yard so that you can adopt these new technologies with minimal effort. Starting today, we are enhancing our platinum support plan to include support for (a) stack migrations to v7 and (b) migration of your applications to Graviton &#8211; both of which would save significantly on your cloud spend.</span></p><p><span style="font-weight: 400;">Looking forward to working with you on your migration. If you have any questions, please reach out to us <a href="mailto:customersuccess@engineyard.com">customersuccess@engineyard.com</a></span></p>						</div>
				</div>
					</div>
		</div>
							</div>
		</section>
							</div>
		<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-stack-v7-is-now-generally-available/">Engine Yard stack v7 is now generally available</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Engine Yard Innovation Event</title>
		<link>https://www.engineyard.com/blog/engine-yard-innovation-event/</link>
		
		<dc:creator><![CDATA[Daniel Valfre]]></dc:creator>
		<pubDate>Mon, 18 Apr 2022 12:31:25 +0000</pubDate>
				<category><![CDATA[Application Deployment]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/?p=3657</guid>

					<description><![CDATA[<p>Recap of Engine Yard Innovation Event Thank you for making the Engine Yard Innovation Event successful. It was a pleasure seeing many of our Engine Yard customers participate in the event. To recap, here are some exciting innovations we announced at the event: Availability of CloudFix, AWS Cost Optimization platform, for Engine Yard customers Support [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-innovation-event/">Engine Yard Innovation Event</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="3657" class="elementor elementor-3657">
									<section class="elementor-section elementor-top-section elementor-element elementor-element-f6787c4 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="f6787c4" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-8f1728b" data-id="8f1728b" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-ee1a292 elementor-widget elementor-widget-video" data-id="ee1a292" data-element_type="widget" data-settings="{&quot;youtube_url&quot;:&quot;https:\/\/www.youtube.com\/watch?v=xH7KO0KHibc&quot;,&quot;show_image_overlay&quot;:&quot;yes&quot;,&quot;image_overlay&quot;:{&quot;url&quot;:&quot;https:\/\/www.engineyard.com\/wp-content\/uploads\/2022\/04\/ey-innovation-event-14-apr-22-v5-01.png&quot;,&quot;id&quot;:3661,&quot;size&quot;:&quot;&quot;,&quot;alt&quot;:&quot;&quot;,&quot;source&quot;:&quot;library&quot;},&quot;lightbox&quot;:&quot;yes&quot;,&quot;video_type&quot;:&quot;youtube&quot;,&quot;controls&quot;:&quot;yes&quot;}" data-widget_type="video.default">
				<div class="elementor-widget-container">
			<style>/*! elementor - v3.11.2 - 22-02-2023 */
.elementor-widget-video .elementor-widget-container{overflow:hidden;transform:translateZ(0)}.elementor-widget-video .elementor-wrapper iframe,.elementor-widget-video .elementor-wrapper video{height:100%;width:100%;border:none;background-color:#000}.elementor-widget-video .elementor-open-inline .elementor-custom-embed-image-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:50%}.elementor-widget-video .elementor-custom-embed-image-overlay{cursor:pointer;text-align:center}.elementor-widget-video .elementor-custom-embed-image-overlay:hover .elementor-custom-embed-play i{opacity:1}.elementor-widget-video .elementor-custom-embed-image-overlay img{display:block;width:100%}.elementor-widget-video .e-hosted-video .elementor-video{-o-object-fit:cover;object-fit:cover}.e-con-inner>.elementor-widget-video,.e-con>.elementor-widget-video{width:var(--container-widget-width);--flex-grow:var(--container-widget-flex-grow)}</style>		<div class="elementor-wrapper elementor-open-lightbox">
							<div class="elementor-custom-embed-image-overlay" data-elementor-open-lightbox="yes" data-elementor-lightbox="{&quot;type&quot;:&quot;video&quot;,&quot;videoType&quot;:&quot;youtube&quot;,&quot;url&quot;:&quot;https:\/\/www.youtube.com\/embed\/xH7KO0KHibc?feature=oembed&amp;start&amp;end&amp;wmode=opaque&amp;loop=0&amp;controls=1&amp;mute=0&amp;rel=0&amp;modestbranding=0&quot;,&quot;modalOptions&quot;:{&quot;id&quot;:&quot;elementor-lightbox-ee1a292&quot;,&quot;entranceAnimation&quot;:&quot;&quot;,&quot;entranceAnimation_tablet&quot;:&quot;&quot;,&quot;entranceAnimation_mobile&quot;:&quot;&quot;,&quot;videoAspectRatio&quot;:&quot;169&quot;}}" data-e-action-hash="#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJ0eXBlIjoidmlkZW8iLCJ2aWRlb1R5cGUiOiJ5b3V0dWJlIiwidXJsIjoiaHR0cHM6XC9cL3d3dy55b3V0dWJlLmNvbVwvZW1iZWRcL3hIN0tPMEtIaWJjP2ZlYXR1cmU9b2VtYmVkJnN0YXJ0JmVuZCZ3bW9kZT1vcGFxdWUmbG9vcD0wJmNvbnRyb2xzPTEmbXV0ZT0wJnJlbD0wJm1vZGVzdGJyYW5kaW5nPTAiLCJtb2RhbE9wdGlvbnMiOnsiaWQiOiJlbGVtZW50b3ItbGlnaHRib3gtZWUxYTI5MiIsImVudHJhbmNlQW5pbWF0aW9uIjoiIiwiZW50cmFuY2VBbmltYXRpb25fdGFibGV0IjoiIiwiZW50cmFuY2VBbmltYXRpb25fbW9iaWxlIjoiIiwidmlkZW9Bc3BlY3RSYXRpbyI6IjE2OSJ9fQ%3D%3D">
											<img fetchpriority="high" decoding="async" width="1200" height="628" src="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-14-apr-22-v5-01.png" class="attachment-full size-full wp-image-3661" alt="" srcset="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-14-apr-22-v5-01.png 1200w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-14-apr-22-v5-01-300x157.png 300w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-14-apr-22-v5-01-1024x536.png 1024w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-14-apr-22-v5-01-768x402.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" />																<div class="elementor-custom-embed-play" role="button" aria-label="Play Video" tabindex="0">
							<i aria-hidden="true" class="eicon-play"></i>							<span class="elementor-screen-only">Play Video</span>
						</div>
									</div>
					</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-73386a2 elementor-widget elementor-widget-heading" data-id="73386a2" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<style>/*! elementor - v3.11.2 - 22-02-2023 */
.elementor-heading-title{padding:0;margin:0;line-height:1}.elementor-widget-heading .elementor-heading-title[class*=elementor-size-]>a{color:inherit;font-size:inherit;line-height:inherit}.elementor-widget-heading .elementor-heading-title.elementor-size-small{font-size:15px}.elementor-widget-heading .elementor-heading-title.elementor-size-medium{font-size:19px}.elementor-widget-heading .elementor-heading-title.elementor-size-large{font-size:29px}.elementor-widget-heading .elementor-heading-title.elementor-size-xl{font-size:39px}.elementor-widget-heading .elementor-heading-title.elementor-size-xxl{font-size:59px}</style><p class="elementor-heading-title elementor-size-default">Recap of Engine Yard Innovation Event</p>		</div>
				</div>
				<div class="elementor-element elementor-element-a32bcf9 elementor-widget elementor-widget-text-editor" data-id="a32bcf9" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Thank you for making the Engine Yard Innovation Event successful. It was a pleasure seeing many of our Engine Yard customers participate in the event. To recap, here are some exciting innovations we announced at the event:</span></p><ol><li><span style="font-weight: 400;">Availability of CloudFix, AWS Cost Optimization platform, for Engine Yard customers</span></li><li><span style="font-weight: 400;">Support for Graviton processors across the platform</span></li><li><span style="font-weight: 400;">Updated Engine Yard v7 stack</span></li><li>General availability of DevSpaces cloud dev environments</li></ol><h3>CloudFix</h3><p>CloudFix is the easiest way to save 10% to 20% on your AWS costs with few clicks. CloudFix finds and executes 100% safe, AWS-recommended fixes to save on your AWS spend. As a certified AWS partner, CloudFix saves you time and money with zero downtime and zero performance degradation.</p><p>CloudFix is available to Engine Yard customers to run on non-Engine Yard AWS accounts.</p><p><span style="font-weight: 400;">CloudFix is free for Engine Yard customers to run it on their non Engine Yard accounts. It is free up to an annual AWS spend (aggregate of all connected AWS accounts) that is 10x that of your Engine Yard spend. </span><span style="font-weight: 400;">E.g. You spend $2,000/mo on Engine Yard. Your annual spend with Engine Yard is $2,000 * 12 = $24,000. CloudFix is free up to $24,000 * 10x = $240,000 of annual AWS spend.</span></p><h3>Graviton</h3><p>Graviton is an ARM based processor from AWS that delivers up to 40% price-performance over equivalent x86 processor. When AWS releases next version of Graviton processors (aka Graviton 3), the price-performance is expected to improve even more. </p><p>Just like AWS, Engine Yard is making a big bet on ARM and investing in the technology to continue making AWS easier for you. Engine Yard now supports Graviton on both Engine Yard Cloud and on Engine Yard Kontainers. In addition, Engine Yard is committed to supporting Graviton 3 when it&#8217;s available.</p><h3>Engine Yard v7 Stack</h3><p>Engine Yard is releasing v7 stack in preview on both Engine Yard Cloud and on Engine Yard Kontainers.</p><p>v7 stack includes Ubuntu LTS 20.20, Chef 17, Ruby 2.7+, MySQL 5.7, 5.8 and PostgreSQL 10+. Stack v7 fully supports both x86 and ARM processors.</p><h3>DevSpaces</h3><p>DevSpaces offers cloud-based high-performance, clean, consistent dev environments that you can get up and running in seconds. With DevSpaces, you no longer need to spend hours setting up dev environments.</p><p>With DevSpaces, you get memory that can expand up to 100s of GB, unlimited hours &amp; unlimited parallel workspaces. You can collaborate with live sharing and can code anywhere with browser based VS Code.</p><p> </p>						</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-e4053fd elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="e4053fd" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-bb78a24" data-id="bb78a24" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-5644521 elementor-widget elementor-widget-image" data-id="5644521" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
			<style>/*! elementor - v3.11.2 - 22-02-2023 */
.elementor-widget-image{text-align:center}.elementor-widget-image a{display:inline-block}.elementor-widget-image a img[src$=".svg"]{width:48px}.elementor-widget-image img{vertical-align:middle;display:inline-block}</style>												<img decoding="async" width="1200" height="266" src="https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01.png" class="attachment-full size-full wp-image-3664" alt="" srcset="https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01.png 1200w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-300x67.png 300w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-1024x227.png 1024w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-768x170.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" />															</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-8db2e3b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="8db2e3b" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-4d6e939" data-id="4d6e939" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-ae891ad elementor-widget elementor-widget-text-editor" data-id="ae891ad" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>We did not have time for Q&amp;A but here are some FAQs and if you have more questions, please reach out to us.</p>						</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-0b5fbe7 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="0b5fbe7" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-a41ecab" data-id="a41ecab" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-baf0d22 elementor-widget elementor-widget-html" data-id="baf0d22" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			<h3>CloudFix FAQ</h3>
<span style="font-weight: 400; font-size: 14px;">

<p>
<em>Q. Is it safe to connect my AWS account with CloudFix? What permissions are necessary to connect my account to CloudFix?</em>
    <br>
A. It is completely safe. Unless you approve a recommendation, CloudFix does not change anything with your AWS account.
CloudFix is transparent with the permissions it obtains from AWS. You will be able to check the entire CloudFormation template before connecting your AWS account. Further information about CloudFix’s permission model can be found <a href="https://support.cloudfix.com/hc/en-us/articles/4411461544210-CloudFix-Permission-Model">here</a>.
</p>
<p>
<em>Q. Who uses CloudFix? Has the product been proven in the market?</em>
    <br>
A. Since its release, CloudFix has managed over 45K AWS accounts so far and saved 10% to 20% on AWS spend. Organizations of all sizes - including Fortune 500 Enterprises, Govt organizations and medium size technology companies  - use CloudFix to continue saving on their AWS spend.
</p>

<p>
<em>Q. How is CloudFix different from other cloud cost optimization tools?</em>
    <br>
A. Other tools focus on just making recommendations but CloudFix is laser focused on making recommendations that can be implemented automatically and at scale.

CloudFix is here to save you $ on your AWS bill, not just make some recommendations that are complicated to implement.
</p>
<p><em>
Q. Why can’t I just use AWS tools to manage my costs?
</em><br>
A. AWS cost management tools are just the beginning. We use those too but those do not implement fixes at scale; those tools just focus on making recommendations which involve separate effort for implementation.
CloudFix on the other hand focuses on saving $ with little effort and no disruption to the infrastructure. That is why CloudFix savings are real and effortless.
</p>
<p><em>
Q. Can I use CloudFix on my Engine Yard account?
</em><br>
A. No. Engine Yard already runs CloudFix optimizations on your account.
</p>

<p><em>
    Q. How many AWS accounts I can onboard using CloudFix?
</em><br>
A. Unlimited. You can connect as many AWS accounts as you want with CloudFix.
</p>

<p><em>Is CloudFix free for Engine Yard customers?</em><br>
Yes. CloudFix is free for Engine Yard customers to run it on their non Engine Yard accounts. It is free up to an annual AWS spend (aggregate of all connected AWS accounts) that is 10x that of your Engine Yard spend. E.g. You spend $2,000/mo on Engine Yard. Your annual spend with Engine Yard is $2,000 * 12 = $24,000. CloudFix is free up to $24,000 * 10x = $240,000 of annual AWS spend.
</p>

</span>		</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-095aaf3 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="095aaf3" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-74d49d1" data-id="74d49d1" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-fbef532 elementor-widget elementor-widget-image" data-id="fbef532" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
															<img decoding="async" width="1024" height="227" src="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-cloudfix-01-1024x227.png" class="attachment-large size-large wp-image-3667" alt="" srcset="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-cloudfix-01-1024x227.png 1024w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-cloudfix-01-300x67.png 300w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-cloudfix-01-768x170.png 768w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-cloudfix-01.png 1200w" sizes="(max-width: 1024px) 100vw, 1024px" />															</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-b9d9695 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="b9d9695" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-2d7b63e" data-id="2d7b63e" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-0dccd3b elementor-widget elementor-widget-html" data-id="0dccd3b" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			<h3>Graviton FAQ</h3>
<span style="font-weight: 400; font-size: 14px;">

<p><em>Why should I migrate my applications to Graviton?</em><br>
Graviton processors offer better price performance than x86. The current version of Graviton, Graviton 2, offers up to 40% price-performance compared to x86 processors. The next version, Gravitron 3, offers up to 25% more price performance compared to Graviton 2.
    </p>

<p><em>How easy or diffucult is to migrate applications to Graviton?</em><br>
In order for your application to run smoothly on Graviton, all application components including servers and dependent librararies need to be compatible with Graviton. It takes a lot of testing and potentially migrating servers, librararies and your code before your application runs on Graviton. Engine Yard makes it easier for you to migrate your applications to Graviton because Engine Yard pre-tested, migrated all your servers and libraries that come with v7 stack to be Graviton comptatible.
</p>

<p><em>What do I need to do to migrate my applications running on Engine Yard stack to Graviton?</em><br>
Enigne Yard v7 stack is fully compatible with Graviton. You still need to test your applications and potentially make some code changes if necessary but be assured that Engine Yard is committed to working with you on your Graviton migrations.
</p>

<p><em>Does Engine Yard Kontainers support Graviton?</em><br>
Engine Yard supports Graviton across the platform including Engine Yard Cloud,  Engine Yard Kontainers and DevSpaces.
</p>

</span>		</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-77bca2b elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="77bca2b" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-68f14f4" data-id="68f14f4" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-5d39f48 elementor-widget elementor-widget-html" data-id="5d39f48" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			<h3>Engine Yard v7 Stack FAQ</h3>
<span style="font-weight: 400; font-size: 14px;">

<p><em>When is the stack v7 available?</em><br>
Engine Yard v7 is already available in preview. You can work with Engine Yard support team to start migrating and testing your application.
    </p>
    <p><em>Will Engine Yard continue supporting older versions of stacks?</em><br>
Yes. We understand that many of our customers are not ready to change their applications yet. As a result, we will continue supporting older stacks including v4, v5 and v6. However, we strongly recommend that you upgrade application stack as soon as possible because (1) older versions are not secure (2) require additional maintenace (3) it gets a lot harder to continue supporting older versions because there are fewer customers on older stacks.
    </p>
    <p><em>What's in the v7 stack?</em><br>
Engine Yard v7 stack includes Ubuntu LTS 20.20, Chef 17, Ruby 2.7+, MySQL 5.7, 5.8 and PostgreSQL 10+. Stack v7 fully supports both x86 and ARM processors.
    </p>
</span>		</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-a481520 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="a481520" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-186af35" data-id="186af35" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-29012b2 elementor-widget elementor-widget-image" data-id="29012b2" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
															<img loading="lazy" decoding="async" width="1024" height="227" src="https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-1024x227.png" class="attachment-large size-large wp-image-3664" alt="" srcset="https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-1024x227.png 1024w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-300x67.png 300w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01-768x170.png 768w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-reach-us-banner-01.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" />															</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-7e5a106 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="7e5a106" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-01849df" data-id="01849df" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-e1227f3 elementor-widget elementor-widget-html" data-id="e1227f3" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			<h3>DevSpaces FAQ</h3>
<span style="font-weight: 400; font-size: 14px;">

<p><em>Does DevSpaces run in containers?
</em><br>
DevSpaces is a container-based Dev Environment accessible through the browser.
    </p>
    
<p><em>Does DevSpaces work in any browser?
</em><br>
Yes. You can code with DevSpaces in any modern browser. For added convenience, we also have a browser extension (that allows you to open DevSpaces with a single-click from GitHub or other supported repositories). This extension is currently available for Chrome, Edge and Firefox. A Safari browser extension is coming soon.
    </p>
    
<p><em>My project is complex. Can I still use DevSpaces?
</em><br>
DevSpaces works for almost all projects and supports most programming languages. Reach out to us if you have any problems making DevSpaces work for your project.
    </p>
    
<p><em>What happens to my Workspace when I close my browser?
</em><br>
When you close the browser, your workspace remains intact for the next 30 minutes. After 30 minutes, your Workspace will terminate but the file system and preferences will be saved. You can extend the workspace timeout when you have special workloads that require more time to complete.
    </p>
    
<p><em>Can I share my workspace?
</em><br>
    Yes. You can share your live workspace for real time collaboration.
    </p>
    
<p><em>I need a database for my project. Can I install it on DevSpaces?
</em><br>
    Yes. You can install databases like MySQL, PostgreSQL, Redis and MongoDB on your Devspaces.
    </p>
    
<p><em>Is the DevSpaces IDE the same as VS Code?
</em><br>
    Yes. DevSpaces IDE is based on VS Code and you won't miss anything that you are used in VS Code.
    </p>
    
<p><em>Can I install Extensions?
</em><br>
    Yes. You can install and use VS Code extensions with your DevSpaces.
    </p>
    
<p><em>Can I debug applications from the DevSpaces IDE?
</em><br>
    Yes. We have a great video on <a href="https://youtu.be/5MJo4L_q33I">how to debug your applications</a> in DevSpaces IDE.
    </p>
</span>		</div>
				</div>
					</div>
		</div>
							</div>
		</section>
				<section class="elementor-section elementor-top-section elementor-element elementor-element-e689c8c elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="e689c8c" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-300bf34" data-id="300bf34" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-105fff8 elementor-widget elementor-widget-image" data-id="105fff8" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
															<img loading="lazy" decoding="async" width="1024" height="227" src="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-devspaces-01-1024x227.png" class="attachment-large size-large wp-image-3672" alt="" srcset="https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-devspaces-01-1024x227.png 1024w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-devspaces-01-300x67.png 300w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-devspaces-01-768x170.png 768w, https://www.engineyard.com/wp-content/uploads/2022/04/ey-innovation-event-banner-devspaces-01.png 1200w" sizes="auto, (max-width: 1024px) 100vw, 1024px" />															</div>
				</div>
					</div>
		</div>
							</div>
		</section>
							</div>
		<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/engine-yard-innovation-event/">Engine Yard Innovation Event</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>That&#8217;s Not a Memory Leak, It&#8217;s Bloat</title>
		<link>https://www.engineyard.com/blog/thats-not-a-memory-leak-its-bloat/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Wed, 12 Jan 2022 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/thats-not-a-memory-leak-its-bloat/</guid>

					<description><![CDATA[<p>Our Rails customers often run into memory issues. The most frequent cause these days is what we in Support dub ‘bloated mongrels.’ To be fair, bloat has absolutely nothing to do with mongrel itself, which is a solid and fine piece of work. You can run into this problem just as easily with thin, passenger, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/thats-not-a-memory-leak-its-bloat/">That&#8217;s Not a Memory Leak, It&#8217;s Bloat</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="2080" class="elementor elementor-2080">
									<section class="elementor-section elementor-top-section elementor-element elementor-element-287afdc8 elementor-section-boxed elementor-section-height-default elementor-section-height-default" data-id="287afdc8" data-element_type="section">
						<div class="elementor-container elementor-column-gap-default">
					<div class="elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-1694fb7d" data-id="1694fb7d" data-element_type="column">
			<div class="elementor-widget-wrap elementor-element-populated">
								<div class="elementor-element elementor-element-68f73b93 elementor-widget elementor-widget-text-editor" data-id="68f73b93" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>Our Rails customers often run into memory issues. The most frequent cause these days is what we in Support dub ‘bloated mongrels.’</p>
<p></p></div></div></div></div></div></section></div> <a href="https://www.engineyard.com/blog/thats-not-a-memory-leak-its-bloat/#more-2080" class="more-link elementor-more-link"><span aria-label="Continue reading That&#8217;s Not a Memory Leak, It&#8217;s Bloat">(more&hellip;)</span></a><p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/thats-not-a-memory-leak-its-bloat/">That&#8217;s Not a Memory Leak, It&#8217;s Bloat</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Evolution of Encrypted Credentials in Rails 6.2</title>
		<link>https://www.engineyard.com/blog/encrypted-credentials-in-rails-6-2-evolution/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Wed, 27 Oct 2021 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[Ruby Application Deployment]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/encrypted-credentials-in-rails-6-2-evolution/</guid>

					<description><![CDATA[<p>Your blog The concept of encrypted secrets evolved and acquired a better shape with each update of the Rails version. Recently, Rails 6.2 has brought in many such updates to the credentials feature. Let us analyze and discuss encrypted credentials further, how to read them, the advantages, and finally, how to manage a secret key [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/encrypted-credentials-in-rails-6-2-evolution/">Evolution of Encrypted Credentials in Rails 6.2</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Your blog The concept of encrypted secrets evolved and acquired a better shape with each update of the <a href="https://weblog.rubyonrails.org/releases/" style="color: #4a6ee0;"><span>Rails version</span></a>. Recently, Rails 6.2 has brought in many such updates to the credentials feature. Let us analyze and discuss encrypted credentials further, how to read them, the advantages, and finally, how to manage a secret key base.</p>
<p><span id="more-2081"></span></p>
<h2 style="font-size: 30px;"><strong>Evolution of Encrypted credentials</strong></h2>
<p style="font-weight: normal;">Encrypted secrets were introduced with Rails 5.1 in a view to bringing more security to the secrets handled. In this version, these were referred to as ‘<em>secrets</em>’ and were referenced by</p>
<p style="font-weight: normal;"><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image2-4.png" alt="Rails Encrypted credentials" width="620" loading="lazy" style="width: 620px;"></p>
<p><span style="font-size: 16px;"><span style="color: #0e101a;">The </span><em><span style="color: #0e101a;">secrets.yml.enc </span></em><span style="color: #0e101a;">file handles the secrets along with an encryption key.</span></span></p>
<h2 style="font-size: 30px;"><span style="color: #0e101a;"><strong>Handling secrets before Rails 5.1</strong></span></h2>
<p>&nbsp;Before this version of Rails, there were two methods to commit the secrets.&nbsp;<span style="color: #0e101a;"></span></p>
<ul>
<li aria-level="1">The first method was to store secrets onto the <em>secrets.yml</em> file, read secrets from environment variables, and commit the <em>secrets.yml</em> file to the repository. Though this method was easy to operate, it had a high-security risk as any gem used can dump environment variables. Since the data is open and not encrypted, this can be read by anyone accessing the repository.</li>
<li aria-level="1">The second method was to store all secrets in the <em style="color: #0e101a; background-color: transparent;">secrets.yml</em><span style="color: #0e101a; background-color: transparent;"> file and not commit them to the repository.</span></li>
</ul>
<h2 style="font-size: 30px;"><span style="color: #0e101a; background-color: transparent;"><strong>Handling secrets in Rails 5.1</strong></span></h2>
<p><span style="font-size: 16px;"><span style="color: #0e101a;">By default, from this version of Rails, the secrets were passed as secrets.yml file along with an encryption key. Without this key, the secrets stored in the file will look like some junk characters. To initiate using secrets, the user needs to run:</span><span style="color: #0e101a; background-color: transparent;"></span></span></p>
<p><span style="font-size: 16px;"><span style="color: #0e101a;"><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image2-Oct-27-2021-10-26-52-86-AM.png" alt="encrypted credentias in rails 5.1" width="620" loading="lazy" style="width: 620px;"></span></span></p>
<p><span style="font-size: 16px;"><span style="color: #0e101a;">This would create two files: </span><em><span style="color: #0e101a;">config/secrets.yml.key</span></em><span style="color: #0e101a;"> and </span><em><span style="color: #0e101a;">config/secrets.yml.enc</span></em><span style="color: #0e101a;">. The </span><em><span style="color: #0e101a;">key</span></em><span style="color: #0e101a;"> file will hold the secret key to decrypt data in the </span><em><span style="color: #0e101a;">enc</span></em><span style="color: #0e101a;"> file.</span></span><span style="color: #0e101a; background-color: transparent;"></span></p>
<h2 style="font-size: 30px;"><strong><span style="color: #0e101a;">Encrypted Credentials in Rails 5.2</span></strong></h2>
<p>An update to the older secret handling, this Rails version removed plain text secrets, and only encrypted credentials were allowed. Credentials were stored in <em>config/credentials.yml.enc,</em> and the key was stored on <em>config/master.key</em>. Thus users could deploy code and credentials together and store all credentials in one place.</p>
<p>Here, multi-environment credentials were handled by specifying explicitly, and the configuration was accessed by mentioning the <em>access_key_id</em>.</p>
<h2 style="font-size: 30px;"><strong>Encrypted Multi-environment Credentials in Rails 6.1</strong></h2>
<p style="font-size: 16px;"><span style="color: #0e101a;">The latest update made it to separate credential files for each environment. This built-in feature necessitates </span><a href="https://github.com/rails/rails/pull/33521" style="font-size: 12px; color: #4a6ee0;"><span><span style="font-size: 16px;">separate encryption key</span></span></a><span style="color: #0e101a;">for each credential file, thus guaranteeing more security.</span><span style="color: #0e101a; background-color: transparent;"></span></p>
<p style="font-size: 16px;"><span style="color: #0e101a;">A global credential file is enough for multiple environments. And when the environment is passed, two files would be created:</span><span style="color: #0e101a; background-color: transparent;"></span></p>
<p style="font-size: 16px;"><span style="color: #0e101a;"><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image3-3.png" alt="global credential file in rails" width="626" loading="lazy" style="width: 626px;"></span></p>
<p style="font-size: 16px;"><span style="color: #0e101a;">Here’s an example of how it works:</span><span style="color: #0e101a; background-color: transparent;"></span></p>
<p style="font-size: 16px;"><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image5-2.png" alt="global credential file in rails" width="628" loading="lazy" style="width: 628px;"></p>
<p style="font-size: 16px;"><span style="color: #0e101a;">If the environment file is missing or not created, the default </span><em><span style="color: #0e101a;">credentials.yml.enc</span></em><span style="color: #0e101a;"> file will be used.</span></p>
<p style="font-size: 16px;"><span style="color: #0e101a; background-color: transparent;"><strong><br />
</strong><span style="font-weight: normal;"><span style="color: #0e101a;">Also, the </span><em><span style="color: #0e101a;">config/credential/prod.yml.enc file</span></em><span style="color: #0e101a;"> would be committed to the repository, whereas the </span><em><span style="color: #0e101a;">config/credential/prod.key </span></em><span style="color: #0e101a;">file would not.</span></span></span></p>
<h2 style="font-size: 30px;"><span style="color: #0e101a; background-color: transparent;"><span style="font-weight: normal;"><span style="color: #0e101a;"><strong>Add-ons in Rails 6</strong></span></span></span></h2>
<ul style="font-size: 16px;">
<li aria-level="1">It is now possible to store the credentials in a location of your choice. This is explicitly mentioned by running:</li>
</ul>
<p style="font-size: 16px;"><em>config.credentials.content_path </em>and<em>&nbsp;</em></p>
<p style="font-size: 16px;"><em>config.credentials.key_path</em></p>
<p style="font-size: 16px;">Make sure to save the valid key and the credentials to avoid errors while running the code.&nbsp;</p>
<ul style="font-size: 16px;">
<li aria-level="1">Handle local environment credentials using</li>
</ul>
<p style="font-size: 16px;"><em>config/credentials/environment.key</em> and<em>&nbsp;</em></p>
<p style="font-size: 16px;"><em>config/master.key</em></p>
<ul style="font-size: 16px;">
<li aria-level="1"><em>The below command tells Rails to search the credentials file in path config/credentials/local.yml.enc instead of config/credentials/development.yml.enc</em></li>
</ul>
<p style="font-size: 16px;"><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image4-4.png" alt="Add-ons in rails 6.1" width="625" loading="lazy" style="width: 625px;"></p>
<p style="font-size: 16px;"><span style="color: #0e101a; background-color: transparent;"><span style="font-weight: normal;"><span style="color: #0e101a;"><strong><br />
</strong><span style="font-weight: normal;">Our latest guide </span><a href="https://www.engineyard.com/blog/rails-encrypted-credentials-on-6.2/" style="font-size: 12px; font-weight: normal;"><span style="font-size: 16px;">Rails encrypted credentials on 6.2</span></a><span style="font-weight: normal;">offer an interesting peek into the Rails credentials.</span></span></span></span></p>
<h2 style="font-size: 30px;"><span style="color: #0e101a; background-color: transparent;"><span style="font-weight: normal;"><span style="color: #0e101a;"><span style="font-weight: normal;"><strong>Advantages of encrypted credentials</strong></span></span></span></span></h2>
<p>The main advantages of encrypted multi-environment credentials are as follows:</p>
<ul>
<li aria-level="1">Safety: The separate encryption key for each environment makes it safer</li>
<li aria-level="1">Easy deployments: since the variables can be moved along with the code, deployments become easier</li>
<li aria-level="1">A single upload of the key is enough</li>
<li aria-level="1">The solution applies to any of the Ruby on Rails applications</li>
</ul>
<h2 style="font-size: 30px;"><strong>Conclusion</strong></h2>
<p>Rails is constantly improving the efficiency and scalability of the framework. With the multi-environment credentials enabled, applications used in multiple platforms and POD find it easier to keep the codes simple and accessible.<span style="color: #0e101a; background-color: transparent;"><span style="font-weight: normal;"><span style="color: #0e101a;"><span style="font-weight: normal;"></span></span></span></span></p>
<p>Know how to use <a href="https://support.cloud.engineyard.com/hc/en-us/articles/360058941713-How-Kontainers-Works" style="color: #4a6ee0;"><span>Engine Yard Kontainers</span></a>to connect to your database, enabling the Rails credentials for improved security.</p>
<p><span style="color: #0e101a; background-color: transparent;"><span style="font-weight: normal;"><span style="color: #0e101a;"><span style="font-weight: normal;">To learn more about the older versions of credentials, check out <a href="https://www.engineyard.com/blog/encrypted-rails-secrets-on-rails-5.1/" style="font-weight: normal;">Encrypted Rails Secrets on Rails 5.1</a></span></span></span></span></p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/encrypted-credentials-in-rails-6-2-evolution/">Evolution of Encrypted Credentials in Rails 6.2</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Rewrite Rules in Nginx</title>
		<link>https://www.engineyard.com/blog/rewrite-rules-nginx/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Wed, 20 Oct 2021 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[App Development]]></category>
		<category><![CDATA[engine yard kontainers]]></category>
		<category><![CDATA[NoOps]]></category>
		<category><![CDATA[Ruby for Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/rewrite-rules-nginx/</guid>

					<description><![CDATA[<p>Rewrite rules modify a part or whole of the URL. This is done for two reasons. First, to inform clients about the relocation of resources, and second, to control the flow to Nginx. The two general-purpose methods used widely for rewriting URLs are the return directive and the rewrite directive. Of these, the rewrite directive [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/rewrite-rules-nginx/">Rewrite Rules in Nginx</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><em>Rewrite rules</em> modify a part or whole of the URL. This is done for two reasons. First, to inform clients about the relocation of resources, and second, to control the flow to Nginx. The two general-purpose methods used widely for rewriting URLs are the <em>return</em> directive and the <em>rewrite</em> directive. Of these, the rewrite directive is more powerful. Let&#8217;s discuss why it is so, as well as how to rewrite the URLs.</p>
<p><span id="more-2082"></span></p>
<p>Having a better <a href="https://www.thegeekstuff.com/2013/11/nginx-vs-apache/" style="color: #4a6ee0;"><span>understanding of NGINX</span></a>will make it easier to follow this blog.</p>
<p><span style="font-size: 18px;"><strong><em>Return </em></strong><strong>directive</strong></span></p>
<p><em>Return </em>is the easiest way to rewrite a URL declared in the server or local machine.</p>
<p><span style="font-size: 18px;"><strong><em>Return </em></strong><strong>in Server:</strong></span></p>
<p>Suppose your site is migrated to a new domain and all existing URLs are to be redirected here; run the below code to direct any new request to your site.</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image1-3.png" alt="Return in Server - Rewrite rule in Ngnix" width="620" loading="lazy" style="width: 620px;"></p>
<p>This directs all requests that hit www.<em>previousdomain.com </em>to <em>www.currentdomain.com. </em>The www.<em>previousomain.com </em>will send out a &#8216;301&#8217; error as soon as the above code is run, and a new access request is generated. The two variables, <em>$scheme</em>, and <em>$request_uri, </em>get data from the input URL. &#8216;<em>Listen 80&#8242;</em> indicates that the block applies to both HTTP and HTTPS requests.</p>
<p><span style="font-size: 18px;"><strong><em>Return </em></strong><strong>in local</strong></span></p>
<p>If you want to redirect pages in place of a complete domain, you can use the <em>return </em>directive under the location block.</p>
<p>Knowing <a href="https://www.nginx.com/blog/creating-nginx-rewrite-rules/" style="color: #4a6ee0;"><span>how to create the Nginx rewrite</span></a>rules can save a lot of your effort and time.</p>
<p><span style="font-size: 18px;"><strong>Rewrite directive</strong></span></p>
<p>Just like the <em>return </em>directive, the rewrite directive can also act in both server and local. Compared to the <em>return</em> directive, the <em>rewrite </em>directive can handle complex replacements of URLs. The following is the syntax of the <em>rewrite</em>:</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image3-2.png" alt="rewrite directive - Rewrite rule in Ngnix" width="627" loading="lazy" style="width: 627px;"></p>
<p>The <em>regex</em> is a regular expression that matches against incoming URI.</p>
<p>The <em>replacement_url </em>is the string used to change the requested URI.</p>
<p>The value of the <em>flag </em>decides if any more redirection or processing is necessary.</p>
<p><span style="font-size: 18px;"><strong>Static page</strong><strong><em> rewrite</em></strong></span></p>
<p>Suppose you want to redirect the page <em>https://example.com/tutorial</em> to <em>https://example.com/new_page</em>. The directive will be:</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image2-3.png" alt="static page rewrite - Rewrite rule in Ngnix" width="622" loading="lazy" style="width: 622px;"></p>
<p>The line <em>location = /tutorial </em>defines that any identification of the tutorial is to be replaced. The <em>rewrite </em>command says to replace the phrase within notations <em>^ </em>and $ with &#8216;<em>new_page.html&#8217; </em>and then break the command. The notation &#8216;?&#8217; is termed as a non-greedy modifier, after which the pattern search is stopped.</p>
<p><span style="font-size: 18px;"><strong>Dynamic page </strong><strong><em>rewrite</em></strong></span></p>
<p>Consider rewriting the URL <em>https://www.sample.com/user.php?id=11 </em>to <em>https://www.sample.com/user/11</em>. Here, the user=11 is to be replaced. By using the static rewrite method, it would require writing the rewrite command 10 times. Instead, let&#8217;s do it in a single go.</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image4-3.png" alt="dynamic page rewrite - Rewrite rule in Ngnix" width="622" loading="lazy" style="width: 622px;"></p>
<p>The line <em>location = /user.php </em>asks Nginx to check for the prefix&#8217;/user&#8217;. As said earlier, the Nginx will search for phrases between the start and end notations as <em>^ </em>&nbsp;and $ along with the non-greedy &#8216;?&#8217; modifier. The phrase in our example is a range of users. It is mentioned inside the square brackets as [0-9]+. The back-reference in this expression is noted within the parenthesis and is referred to by the $1 symbol. So, for our example, the rewrite will happen for all users automatically.&nbsp;</p>
<p>One special case under the dynamic reference is the multiple back-references.&nbsp;</p>
<p>Now, we have discussed how to write the rewrite rules for simple and complex URLs.</p>
<p>Understand the detailed working of rewrite rules through some <a href="https://www.thegeekstuff.com/2017/08/nginx-rewrite-examples/" style="color: #4a6ee0;"><span>examples</span></a>handling various scenarios.</p>


<p class="has-text-align-center has-background" style="background-color:#efefef"><em><strong>Scale performance. Not price.</strong> Try Engine Yard today and enjoy our great support and huge scaling potential for 14 days.</em> <br><em><a href="https://www.engineyard.com/"><span class="popup-trigger popmake-781" data-popup-id="781" data-do-default="0"><strong>Deploy your app for free with Engine Yard</strong></span></a></em>.</p>


<h2 style="font-size: 30px;"><strong>Directive Comparison</strong></h2>
<p>Let&#8217;s analyze both directives by comparing them and find out why the rewrite derivative is more powerful.</p>
<p style="font-size: 18px;"><strong>Return directive</strong></p>
<ul>
<li aria-level="1">It is simple to use and understand.&nbsp;</li>
<li aria-level="1">It can be used in both server and location contexts.&nbsp;</li>
<li aria-level="1">It explicitly mentions the corrected or updated URL so that the client can use them in the future.&nbsp;</li>
<li aria-level="1">Return directives can include multiple error codes as well.</li>
<li aria-level="1">For codes 301, 302, 303, and 307, the URL parameters define the redirect URL.&nbsp;</li>
</ul>
<p style="padding-left: 40px;"><em>return (301 | 302 | 303 | 307) url;</em></p>
<ul>
<li aria-level="1">For other codes, the text is to be explicitly mentioned by the user.&nbsp;</li>
</ul>
<p><em>return (1xx | 2xx | 4xx | 5xx) [&#8216;text&#8217;];</em></p>
<p>For example: <em>return 401 &#8216;Access denied because the token is expired or invalid&#8217;;</em></p>
<ul>
<li aria-level="1">This directive can be used in scenarios where the return URL is correct for both server and location block, and rewritten URL is built with Nginx variables.</li>
</ul>
<p><span style="font-size: 18px;"><strong>Rewrite directive</strong></span></p>
<ul>
<li aria-level="1">It can accommodate more complex URL modifications where capturing elements without Nginx variables or an update in the elements in the path is required.</li>
<li aria-level="1">It can be used in both server and location contexts.&nbsp;</li>
<li aria-level="1">The rewrite directive can return only code 301 or 302. To accommodate other codes, explicitly add the return directive after the rewrite directive.</li>
<li aria-level="1">It may not send the redirect details to the client.</li>
<li aria-level="1">The Nginx request processing is not halted.</li>
</ul>
<h2><span style="font-size: 30px;"><strong>Conclusion</strong></span></h2>
<p>The <em>return</em> and <em>rewrite</em> directives can be used to redirect URLs in both server and location contexts. Though the return directive is much simpler, the rewrite directive is widely used as it can also handle complex modifications/updates to the URLs.</p><p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/rewrite-rules-nginx/">Rewrite Rules in Nginx</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Code Concurrency and Two Easy Fixes</title>
		<link>https://www.engineyard.com/blog/code-concurrency-and-fixes/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Tue, 12 Oct 2021 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/code-concurrency-and-fixes/</guid>

					<description><![CDATA[<p>Code concurrency is a default in any Rails code. A threaded web serverwill simultaneously serve many HTTP requests, and each will hold its controller instance. Threaded active job adapters and action cable channels also handle multiple requests simultaneously. Even when the global process space is shared, work for each instance is managed separately. For scenarios [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/code-concurrency-and-fixes/">Code Concurrency and Two Easy Fixes</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Code concurrency is a default in any Rails code. A <a href="https://www.geeksforgeeks.org/multithreaded-servers-in-java/" style="color: #4a6ee0;"><span>threaded web server</span></a>will simultaneously serve many HTTP requests, and each will hold its controller instance. Threaded active job adapters and action cable channels also handle multiple requests simultaneously. Even when the global process space is shared, work for each instance is managed separately. For scenarios where the shared space is not altered, this process will run smoothly.</p>
<p><span id="more-2083"></span></p>
<p>Let us see in detail how this is managed in our Rails applications.</p>
<ol>
<li aria-level="1"><strong>Executor: Executors separate the framework and application codes by wrapping the application code.</strong></li>
</ol>
<p>The wrapping of code was more complex before Rails 5.0. To protect a code, either separate Rack middleware classes were used or direct wrapping was used. With recent updates in Rails, the executor handles the wrapping in a single step that is easier to understand.</p>
<p>Call the executor to wrap the application code as you invoke it.</p>
<p>For example:</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image1-2.png" alt="Code concurrency Executor example" width="625" loading="lazy" style="width: 625px;"></p>
<p>One attractive feature of the executor is its reentrancy.</p>
<p>Two callbacks of the executor are &#8216;<em><span style="font-weight: bold;">to run</span>&#8216;</em> and &#8216;<span style="font-weight: bold;"><em>to complete</em></span>.&#8217; This enables wrapping code in parts when it is not possible to wrap the code as blocks.</p>
<p><img decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image2-2.png" alt="code concurrency fix example" width="629" loading="lazy" style="width: 629px;"></p>
<p>The current thread is moved to the &#8216;<em>running&#8217; </em>mode, temporarily blocking the thread. So, the thread will not be accessible by any other request that tries to do so.</p>
<ol start="2">
<li><strong> Reloader: The Reloader functions similarly to the Executor. The code that is to be protected is wrapped before another request is hit. This is used in scenarios where application code is invoked multiple times by any long-running process. Most often, in Rails, the web requests and Active Jobs are by default wrapped. So the Reloader is rarely used.</strong></li>
</ol>
<p>A Reloader is employed when there is a need to reload the application. When the requested condition asks for reloading, the Reloader delays the application reload until it is secure. And for scenarios where application reloads are mandated, the Reloader waits until the current block is executed and allows the reload. Thus, the code is protected from errors.</p>
<p>The &#8216;<code><em>to_run</em></code>&#8216; and &#8216;<code><em>to_complete</em></code>&#8216; callbacks are used by the Reloader also.</p>
<p>A <em>class unload </em>is involved in the Reloader process. Here, all of the auto-loaded classes are removed and set ready to be further loaded. The application reload is to happen only before or after the class unload, and so, the two additional callbacks of Reloader are &#8216;<code><em>before_class_unload</em></code>&#8216; and &#8216;<em><code>after_class_unload</code>&#8216;</em>.</p>
<p><a href="https://guides.rubyonrails.org/threading_and_code_execution.html" style="color: #4a6ee0;"><span>Executor and Reloaders</span></a>are used by the Rails framework components as well. <code><em>ActionDispatch::Executor</em></code> and <code><em>ActionDispatch::Reloader </em></code>are included in the default application stack. Whenever there is a code change, the Reloader serves a fresh copy of the application for an HTTP request. Active Job feature also utilizes Reloaders, whereas Action Cable uses Executor. Action Cable also uses the before_class_unload of Reloader to disconnect all the connections.</p>
<p>As discussed, code concurrency is handled by default with the threaded active jobs and action cables features of Rails codes. With <a href="https://weblog.rubyonrails.org/releases/" style="color: #4a6ee0;"><span>recent Rails updates</span></a>, Executors and Reloaders are also added to improve the code concurrency handling.</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/code-concurrency-and-fixes/">Code Concurrency and Two Easy Fixes</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sending iOS Push Notifications via APNs</title>
		<link>https://www.engineyard.com/blog/ios-push-notifications-via-apns-2/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Mon, 04 Oct 2021 08:04:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[engine yard kontainers]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/?p=3446</guid>

					<description><![CDATA[<p>User engagement is of the highest importance in today&#8217;s world, no matter what you sell or offer to your clients. And mobile phone notifications play the masterstroke in this aspect. By regular interactions with your clients through push notifications, it is possible to release timely updates and stay connected with them. So, let us discuss [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/ios-push-notifications-via-apns-2/">Sending iOS Push Notifications via APNs</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image"><img decoding="async" src="https://f.hubspotusercontent30.net/hubfs/4572587/jamie-street-33oxtOMk6Ac-unsplash.jpg" alt="iOS Push Notifications via APNs"/></figure>



<p>User engagement is of the highest importance in today&#8217;s world, no matter what you sell or offer to your clients. And mobile phone notifications play the masterstroke in this aspect. By regular interactions with your clients through push notifications, it is possible to release timely updates and stay connected with them. So, let us discuss setting up an Apple push notification service (APN) with a Node.js application today.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1" height="1" src="https://www.engineyard.com/wp-content/uploads/2022/02/image-4.gif" alt="" class="wp-image-3447"/></figure>



<p>In this blog, we will discuss in detail the APN services, enable and register for remote notifications, device token ids, and APN node package with the help of a sample iOS. Make sure to have a physical iOS device, as push notifications won&#8217;t work with the simulator. Also, an Apple Developer Program Membership account is a must for creating a Push Notifications Certificate.</p>



<h2 class="wp-block-heading">Getting to know about the Remote Notification Service</h2>



<p>Apple devices use a remote notification service to send and receive notifications in any of the iOS, tvOS, or macOS. The remote notification setup is to be configured in your Apple device with proper device tokens and certificates. Otherwise, there are possibilities that the notification services don&#8217;t work as expected.&nbsp;</p>



<p>The main component of this remote notification setup is the Apple Push Notification service, also known as APNs. APN in actuality is a collection of services that allows the developer to send the notifications from their server to the targeted iOS devices. The APNs are robust and secure methods to establish a connection between the provider server and individual Apple devices.&nbsp;</p>



<p>APN contains two components, the <em>Gateway component,</em> and the <em>Feedback component, </em>both of which are must-haves.&nbsp;</p>



<p>Gateway component establishes the TLS connection from a provider side which enables the provider server to send messages to the Apple, which will be processed by Apple and then forwarded to the respective device. It is recommended to keep the connection in an &#8216;always-on&#8217; mode. The <em>Feedback Component </em>is established only occasionally to identify and remove the devices which no longer receive notifications for specific applications. This is a mandatory component in any Apple device.</p>



<p>To receive and handle the remote notifications, the app you provide must have four components as basics. They are:</p>



<ol class="wp-block-list"><li>Remote connection enabled</li><li>A registered Apple Push Notification Service (APN) and device token</li><li>Sending device token to the notification provider</li><li>Establish support to handle incoming notifications in the device</li></ol>



<p>Once the push notification setup is complete in your apps and the provider server-side, the providers can send notification requests to APNs. they convey the notification payloads to each targeted device. As the notification is received, the payload is delivered to the respective app and user communications are managed. It is great to note that the APNs hold the notifications if the device is powered off and waits till the device turns power on while trying multiple times to deliver the message to the appropriate app in the device. This makes it perfect for the user and the provider not to miss any important communication.</p>



<p>It is good to have a clear and strong <a href="https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1">understanding of the APNs</a>, direct from Apple’s guides.</p>



<p>The provider is entitled to many responsibilities. Some of the major ones are below:</p>



<ul class="wp-block-list"><li>Receive globally unique, app-specific device tokens and all relevant data pertaining to your app on user’s devices.</li><li>Determine when the remote notifications are to be sent to each device.</li><li>Building and sending notification requests to APNs.</li></ul>



<p>Only with proper entitlements to talk to APNs, can the app handle the remote notifications. Without these entitlements, the apps are rejected by the App Store. Know the details of entitlements required for your app in the <a href="https://developer.apple.com/documentation/xcode">‘Enable push notification’</a>section of the Xcode Help page on Apple’s website. Once notification pushes are enabled, app registration is a must every time the app is launched. The process of app registering includes the below steps, for all Apple devices.</p>



<ul class="wp-block-list"><li>Your app asks to be registered with APNs</li><li>APNs sends app-specific device tokens</li><li>The system delivers the device to your app by calling a method in your app delegate</li><li>The device token is shared with the app’s associated provider&nbsp;</li></ul>



<p>A method <a href="https://developer.apple.com/documentation/uikit/uiapplication/1623078-registerforremotenotifications">registerForRemoteNotifications</a>is called at the launch time by your app. This initiates the app object to contact APN for app-specific device tokens. Below code shows how to fetch your device token:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/LKGo7PhKHC-qH2W3x9XQJD017qttXmcv5bHQ8Y2dtOThasw-yLZiTIWAvp98pyujpy_E6NMteiOdmMGA5Qi3l5f8BAPEbYNhjMhn0HP3Tz4y_2rLBflfqzRAAI3q7SgEzKNN5TA=s0" alt="fetch your device token"/></figure>



<p>Swift:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/9GZhmVgaIZNubrRSs9ZVtagRbQBZUqWZEkHcUHax4Yk6uE0zvuOLONNa6_WlAx12YxPekHr-Rvy5dn3crA1K6jeGJnV0zNe4hDC0TGakhROWvByUi5Smx4lUH5-N5FwdSMrO8lI=s0" alt="how to fetch your device token"/></figure>



<p>Know more about the <a href="https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/HandlingRemoteNotifications.html#//apple_ref/doc/uid/TP40008194-CH6-SW">Remote and Local notifications</a>on Apple’s page.</p>



<p>Thus, the system establishes an encrypted and persistent IP connection between the app and APNS, whenever the app starts on a device. This connection setups and enables the device to receive notifications, thus requires configuration on the Apple development account and necessary certificate creation.</p>



<p>For our servers to communicate with the APNs, a lot of connections and configurations are to be done in Node.js. It is easier to opt for the <em>apn</em> packages with preset code to establish error-free connections. This ready-to-use package is one good choice for the production environment. The package is based on HTTP/2 API and is capable of maximizing the processing and notification delivery. It also collects the not-sent notifications when an error has occurred. The <a href="https://github.com/node-apn/node-apn">official repository of the apn package</a>will gives a better understanding of this topic.</p>



<h2 class="wp-block-heading">Creating Certificates</h2>



<p>One main step in setting up the notification services is the certificate creation, specific to your app and device. This certificate tells the APN that our server has legal permissions to send and receive notifications of our app. That means the SSL certificate establishes a secure connection with the APNs. The certificate for our is created by us and is specific to our app alone.</p>



<p>Proceed with the below steps to create a certificate:</p>



<ol class="wp-block-list"><li>Open the project from Xcode, and select the Capabilities tab from Target.</li><li>Enable Push Notification switch and wait for automatic configuration to be completed.</li><li>In the developer center, search for our app in our developer account. Tap Edit.</li><li>Open the Push Notification section on this screen.</li><li>Open ‘Create Certificate’ in the Development SSL Certificate tab</li><li>Follow the procedure in the upcoming steps on the screen to create a certificate. The certificate will be ready for download once created successfully.</li><li>Download the certificate aps_development.cer.</li><li>Select the certificate and private key from the list and export a p12 file. Type in the password and note to remember the newly created password as it will be needed by Apple to send push notifications.</li></ol>



<h2 class="wp-block-heading">Obtaining device token</h2>



<p>In the above section, we saw the general code to fetch device tokens. Let us consider a scenario-specific code that we can further use for Node.js script creation.</p>



<p>Our sample app is titled SimplRTApp. We need to identify the device tokens to push notifications from the sample app. So, to get the device token, add the following methods on our <em>AppDelegate.swift</em>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/tygXGn37MrpeJzTTUBz5scstyVz7XqSPq6-kSKHnzZAg3h9zCqZAikLBDN8KH-eoIleE0gNSdcyZjU1Wa0lKkEv7_XES2c1bAzHwrjBHXZ1Mjk8pTkvC0sbzGmgbzTKnKA1tQv0=s0" alt="SimplRTApp"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/cVkmf9gADkhUwFxcaqFI4pRsYyIuuKTJ8Y7qYQOs9HSrQFzvqrofg2-a_tuZtRq6YPyheG9jPiy7HxQ-_dwxgrtl-1qeatS2SJ1gUnXrNhB0ZKkJ0Bv1WEfpbuHlDeIoTwC4UPU=s0" alt="SimplRTApp"/></figure>



<p>View the raw code for the below snippets in the <a href="https://gist.githubusercontent.com/fedejordan/9eda97e5d7b895cdb239ada430f13cab/raw/60382f53919d5293a2870b7f05b792d997e708f2/AppDelegate.swift">github library</a>.</p>



<p>Also, check the <a href="https://github.com/fedejordan/SimpleRTApp">final app code for SimpleRTApp</a>for further details.</p>



<h2 class="wp-block-heading">The Node.js Script Creation</h2>



<p>We now have a p12 file to establish a secure connection with the APNs and a device token to send push notifications to this device from our SimpleRTApp. All we need now is to create our program on Node.js and test the push notifications.</p>



<p>To create the Node.js script:</p>



<ol class="wp-block-list"><li>Open the terminal app.</li><li>Need to install the module that handles APN connections. For that, type npm install apn.&nbsp;</li><li>Copy or save the p12 file to the folder same as that of our Node.js script.</li><li>Create the below <a href="https://gist.githubusercontent.com/fedejordan/89cb4fd33a57d18441469748255b1ec6/raw/5972273eae18a920271a4d777f0daefd9841cbcf/send_push.js">script</a>(available from Github).</li></ol>



<figure class="wp-block-image"><img decoding="async" src="https://lh4.googleusercontent.com/QxUH4Xqht-Whh_RDFP_LFJIm6oZE4Oykl7M4998VnupUmFvKrzmj3UMUfQXdAUHv4-g3Ks8ysPLqG6lRgGXvgfmxV-oY5Cjo5zAKOSxgxC-cOazf_ES8rWr5VZ0lLmz3bamdMcQ=s0" alt="Node.js script"/></figure>



<p>In the script, the &lt;device-token&gt; and &lt;p12-password&gt; are replaced by the values specific to our app. The above script does the following to set up a real-time push notification when triggered.</p>



<ul class="wp-block-list"><li>Establish the connection</li><li>Instate the <em>provider </em>object</li><li>Create <em>Notification</em> and send with the <em>send() </em>method</li><li>Finish execution when there is a response for either success or error scenario</li></ul>



<p>With the above script, the push notification setup is complete. Now is the time to test the script. For testing, type node send_push.js in the terminal and wait for the notification to arrive in the mentioned Apple device.</p>



<p><a href="https://github.com/fedejordan/SimpleRTAppAPI">Complete script for the push notification</a> service in check in the GitHub and is available for your reference.&nbsp;</p>



<p>It is a good practice to include a custom action with the notifications. It allows the user to communicate quickly with a proper preset response. Examples for custom actions include the ‘Reply’ or ‘Mark as read’ button in a message notification, ‘Install’ or ‘Snooze’ options in an OS update notification, etc. in our case, one easy and simple custom action would be ‘Retweet’.</p>



<p>Simple edits on the Node.js code shared above will enable these custom actions. Let’s see how to proceed.</p>



<p>While setting the notification object, include below:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/1_BcdX8WAm3OoJPTmZl701u0ZM-ALoXAamdvl-rpC4iaRkxzbL8NK9Y8A8qT8go3UHTqGiFx0yt1Au6km6LLuL4KlEVyToo-zHJ61sasmn4RBQjw8M5IL0ts3MNTd-DDC9Wbr78=s0" alt="Ios notification object"/></figure>



<p>Also, to let the iOS app know it is an allowed action with the below code:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/0_72kEE7PHcs2XcmHll7wuzZNgXiZMnKLvSLs9gIA955xn3PxW21cGyR7T3he5MRq1TA-mz-XkZ6swWI3JY_W4fAdbS1uhIVVmuiwrUtoFjeLu4irBwEGGjt3E8l3SAPDMwY96A=s0" alt="IoS notification object"/></figure>



<p>Thus, for our <em>AppDelegate.swift</em>, the script would be as follows:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/Qkie7ZVQ56xynL5k-WByEWoy0OaMuuGOGUsQhERdpOl4MpAmytjB4yHd_xNiKq4jnqNHfuQVRkIJw-GTmHvpLSJbLMRBCj7dR5WP_BKQIpPKCZKbwQvDGLTI9R8ZpWLTylQ5Be0=s0" alt="AppDelegate.swift notification object"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://lh5.googleusercontent.com/eZoS38d_5sOnoNo_Btfcj1AWOf17TZfpAg2qqxvcpqDkbuGERVgUUXlv0EXOIZW4afbN5Nisp5CSSH7syylx13Omzu_dfQUmr432z9UhvAkXSqk47wtHdVMEkkofrLxhwnUJ1HQ=s0" alt="AppDelegate.swift notification object"/></figure>



<figure class="wp-block-image"><img decoding="async" src="https://lh4.googleusercontent.com/pxxXQS5gKsQMYsDf_zC5fY_BYX1FsINT_r-WA8gsR_3VEEZqI-rSK8kg-QBWA7U13vG-7uDSnGXll7Ik46TdAXd-L9Aihc2_qeNz1zwfh-so3jO0TIl59WI_uZAGy1A6n7il9e8=s0" alt=""/></figure>



<h3 class="wp-block-heading">Conclusion</h3>



<p>As we come to the end of this blog, we have discussed all the below points in detail&nbsp;</p>



<ul class="wp-block-list"><li>The remote notifications</li><li>APNs</li><li>Certificate creation</li><li>Fetching Device tokens</li><li>Node.js code for delivering push notification</li></ul>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/ios-push-notifications-via-apns-2/">Sending iOS Push Notifications via APNs</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Sending iOS Push Notifications via APNs</title>
		<link>https://www.engineyard.com/blog/ios-push-notifications-via-apns/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Mon, 04 Oct 2021 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[engine yard kontainers]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/ios-push-notifications-via-apns/</guid>

					<description><![CDATA[<p>User engagement is of the highest importance in today&#8217;s world, no matter what you sell or offer to your clients. And mobile phone notifications play the masterstroke in this aspect. By regular interactions with your clients through push notifications, it is possible to release timely updates and stay connected with them. So, let us discuss [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/ios-push-notifications-via-apns/">Sending iOS Push Notifications via APNs</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img src='https://www.engineyard.com/wp-content/uploads/2022/02/jamie-street-33oxtOMk6Ac-unsplash.jpg' alt='iOS Push Notifications via APNs' width='640' loading='lazy' style='width: 640px;'></p>
<p>User engagement is of the highest importance in today&#8217;s world, no matter what you sell or offer to your clients. And mobile phone notifications play the masterstroke in this aspect. By regular interactions with your clients through push notifications, it is possible to release timely updates and stay connected with them. So, let us discuss setting up an Apple push notification service (APN) with a Node.js application today.</p>
<p><span id="more-2084"></span></p>
<p>In this blog, we will discuss in detail the APN services, enable and register for remote notifications, device token ids, and APN node package with the help of a sample iOS. Make sure to have a physical iOS device, as push notifications won&#8217;t work with the simulator. Also, an Apple Developer Program Membership account is a must for creating a Push Notifications Certificate.</p>
<h2 style='font-weight: bold;'><span style='font-size: 30px;'>Getting to know about the Remote Notification Service</span></h2>
<p>Apple devices use a remote notification service to send and receive notifications in any of the iOS, tvOS, or macOS. The remote notification setup is to be configured in your Apple device with proper device tokens and certificates. Otherwise, there are possibilities that the notification services don&#8217;t work as expected.&nbsp;</p>
<p>The main component of this remote notification setup is the Apple Push Notification service, also known as APNs. APN in actuality is a collection of services that allows the developer to send the notifications from their server to the targeted iOS devices. The APNs are robust and secure methods to establish a connection between the provider server and individual Apple devices.&nbsp;</p>
<p>APN contains two components, the <em>Gateway component,</em> and the <em>Feedback component, </em>both of which are must-haves.&nbsp;</p>
<p>Gateway component establishes the TLS connection from a provider side which enables the provider server to send messages to the Apple, which will be processed by Apple and then forwarded to the respective device. It is recommended to keep the connection in an &#8216;always-on&#8217; mode. The <em>Feedback Component </em>is established only occasionally to identify and remove the devices which no longer receive notifications for specific applications. This is a mandatory component in any Apple device.</p>
<p>To receive and handle the remote notifications, the app you provide must have four components as basics. They are:</p>
<ol>
<li aria-level='1'>Remote connection enabled</li>
<li aria-level='1'>A registered Apple Push Notification Service (APN) and device token</li>
<li aria-level='1'>Sending device token to the notification provider</li>
<li aria-level='1'>Establish support to handle incoming notifications in the device</li>
</ol>
<p>Once the push notification setup is complete in your apps and the provider server-side, the providers can send notification requests to APNs. they convey the notification payloads to each targeted device. As the notification is received, the payload is delivered to the respective app and user communications are managed. It is great to note that the APNs hold the notifications if the device is powered off and waits till the device turns power on while trying multiple times to deliver the message to the appropriate app in the device. This makes it perfect for the user and the provider not to miss any important communication.</p>
<p>It is good to have a clear and strong <a href='https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/APNSOverview.html#//apple_ref/doc/uid/TP40008194-CH8-SW1'><span>understanding of the APNs</span></a>, direct from Apple’s guides.</p>
<p>The provider is entitled to many responsibilities. Some of the major ones are below:</p>
<ul>
<li aria-level='1'>Receive globally unique, app-specific device tokens and all relevant data pertaining to your app on user’s devices.</li>
<li aria-level='1'>Determine when the remote notifications are to be sent to each device.</li>
<li aria-level='1'>Building and sending notification requests to APNs.</li>
</ul>
<p>Only with proper entitlements to talk to APNs, can the app handle the remote notifications. Without these entitlements, the apps are rejected by the App Store. Know the details of entitlements required for your app in the <a href='https://developer.apple.com/documentation/xcode'><span>‘Enable push notification’</span></a>section of the Xcode Help page on Apple’s website. Once notification pushes are enabled, app registration is a must every time the app is launched. The process of app registering includes the below steps, for all Apple devices.</p>
<ul>
<li aria-level='1'>Your app asks to be registered with APNs</li>
<li aria-level='1'>APNs sends app-specific device tokens</li>
<li aria-level='1'>The system delivers the device to your app by calling a method in your app delegate</li>
<li aria-level='1'>The device token is shared with the app’s associated provider&nbsp;</li>
</ul>
<p>A method <a href='https://developer.apple.com/documentation/uikit/uiapplication/1623078-registerforremotenotifications' style='color: #0088cc;'><span>registerForRemoteNotifications</span></a>is called at the launch time by your app. This initiates the app object to contact APN for app-specific device tokens. Below code shows how to fetch your device token:</p>
<p><img src='https://lh6.googleusercontent.com/LKGo7PhKHC-qH2W3x9XQJD017qttXmcv5bHQ8Y2dtOThasw-yLZiTIWAvp98pyujpy_E6NMteiOdmMGA5Qi3l5f8BAPEbYNhjMhn0HP3Tz4y_2rLBflfqzRAAI3q7SgEzKNN5TA=s0' width='623' height='392' loading='lazy' alt='fetch your device token'></p>
<p>Swift:</p>
<p><img src='https://lh5.googleusercontent.com/9GZhmVgaIZNubrRSs9ZVtagRbQBZUqWZEkHcUHax4Yk6uE0zvuOLONNa6_WlAx12YxPekHr-Rvy5dn3crA1K6jeGJnV0zNe4hDC0TGakhROWvByUi5Smx4lUH5-N5FwdSMrO8lI=s0' width='624' height='357' loading='lazy' alt='how to fetch your device token'></p>
<p>Know more about the <a href='https://developer.apple.com/library/archive/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/HandlingRemoteNotifications.html#//apple_ref/doc/uid/TP40008194-CH6-SW'><span>Remote and Local notifications</span></a>on Apple’s page.</p>
<p>Thus, the system establishes an encrypted and persistent IP connection between the app and APNS, whenever the app starts on a device. This connection setups and enables the device to receive notifications, thus requires configuration on the Apple development account and necessary certificate creation.</p>
<p>For our servers to communicate with the APNs, a lot of connections and configurations are to be done in Node.js. It is easier to opt for the <em>apn</em> packages with preset code to establish error-free connections. This ready-to-use package is one good choice for the production environment. The package is based on HTTP/2 API and is capable of maximizing the processing and notification delivery. It also collects the not-sent notifications when an error has occurred. The <a href='https://github.com/node-apn/node-apn'><span>official repository of the apn package</span></a>will gives a better understanding of this topic.</p>
<h2 style='font-weight: bold; font-size: 30px;'>Creating Certificates</h2>
<p>One main step in setting up the notification services is the certificate creation, specific to your app and device. This certificate tells the APN that our server has legal permissions to send and receive notifications of our app. That means the SSL certificate establishes a secure connection with the APNs. The certificate for our is created by us and is specific to our app alone.</p>
<p>Proceed with the below steps to create a certificate:</p>
<ol>
<li aria-level='1'>Open the project from Xcode, and select the Capabilities tab from Target.</li>
<li aria-level='1'>Enable Push Notification switch and wait for automatic configuration to be completed.</li>
<li aria-level='1'>In the developer center, search for our app in our developer account. Tap Edit.</li>
<li aria-level='1'>Open the Push Notification section on this screen.</li>
<li aria-level='1'>Open ‘Create Certificate’ in the Development SSL Certificate tab</li>
<li aria-level='1'>Follow the procedure in the upcoming steps on the screen to create a certificate. The certificate will be ready for download once created successfully.</li>
<li aria-level='1'>Download the certificate <span style='font-size: 14px; color: #292929; background-color: #f2f2f2;'>aps_development.cer</span>.</li>
<li aria-level='1'>Select the certificate and private key from the list and export a p12 file. Type in the password and note to remember the newly created password as it will be needed by Apple to send push notifications.</li>
</ol>
<h2 style='font-size: 30px; font-weight: bold;'>Obtaining device token</h2>
<p>In the above section, we saw the general code to fetch device tokens. Let us consider a scenario-specific code that we can further use for Node.js script creation.</p>
<p>Our sample app is titled SimplRTApp. We need to identify the device tokens to push notifications from the sample app. So, to get the device token, add the following methods on our <em>AppDelegate.swift</em>.</p>
<p><img src='https://lh6.googleusercontent.com/tygXGn37MrpeJzTTUBz5scstyVz7XqSPq6-kSKHnzZAg3h9zCqZAikLBDN8KH-eoIleE0gNSdcyZjU1Wa0lKkEv7_XES2c1bAzHwrjBHXZ1Mjk8pTkvC0sbzGmgbzTKnKA1tQv0=s0' width='624' height='560' loading='lazy' alt='SimplRTApp'></p>
<p><img src='https://lh5.googleusercontent.com/cVkmf9gADkhUwFxcaqFI4pRsYyIuuKTJ8Y7qYQOs9HSrQFzvqrofg2-a_tuZtRq6YPyheG9jPiy7HxQ-_dwxgrtl-1qeatS2SJ1gUnXrNhB0ZKkJ0Bv1WEfpbuHlDeIoTwC4UPU=s0' width='624' height='327' loading='lazy' alt='SimplRTApp'></p>
<p>View the raw code for the below snippets in the <a href='https://gist.githubusercontent.com/fedejordan/9eda97e5d7b895cdb239ada430f13cab/raw/60382f53919d5293a2870b7f05b792d997e708f2/AppDelegate.swift'><span>github library</span></a>.</p>
<p>Also, check the <a href='https://github.com/fedejordan/SimpleRTApp'><span>final app code for SimpleRTApp</span></a>for further details.</p>
<h2 style='font-size: 30px; font-weight: bold;'>The Node.js Script Creation</h2>
<p>We now have a p12 file to establish a secure connection with the APNs and a device token to send push notifications to this device from our SimpleRTApp. All we need now is to create our program on Node.js and test the push notifications.</p>
<p>To create the Node.js script:</p>
<ol>
<li aria-level='1'>Open the terminal app.</li>
<li aria-level='1'>Need to install the module that handles APN connections. For that, type <span style='font-size: 14px; color: #292929; background-color: #f2f2f2;'>npm install apn</span>.&nbsp;</li>
<li aria-level='1'>Copy or save the p12 file to the folder same as that of our Node.js script.</li>
<li aria-level='1'>Create the below <a href='https://gist.githubusercontent.com/fedejordan/89cb4fd33a57d18441469748255b1ec6/raw/5972273eae18a920271a4d777f0daefd9841cbcf/send_push.js'><span>script</span></a>(available from Github).</li>
</ol>
<p><img src='https://lh4.googleusercontent.com/QxUH4Xqht-Whh_RDFP_LFJIm6oZE4Oykl7M4998VnupUmFvKrzmj3UMUfQXdAUHv4-g3Ks8ysPLqG6lRgGXvgfmxV-oY5Cjo5zAKOSxgxC-cOazf_ES8rWr5VZ0lLmz3bamdMcQ=s0' width='623' height='347' loading='lazy' alt='Node.js script'></p>
<p>In the script, the <span style='font-size: 12px; color: #292929; background-color: #f2f2f2;'>&lt;device-token&gt;</span> and <span style='font-size: 12px; color: #292929; background-color: #f2f2f2;'>&lt;p12-password&gt;</span> are replaced by the values specific to our app. The above script does the following to set up a real-time push notification when triggered.</p>
<ul>
<li aria-level='1'>Establish the connection</li>
<li aria-level='1'>Instate the <em>provider </em>object</li>
<li aria-level='1'>Create <em>Notification</em> and send with the <em>send() </em>method</li>
<li aria-level='1'>Finish execution when there is a response for either success or error scenario</li>
</ul>
<p>With the above script, the push notification setup is complete. Now is the time to test the script. For testing, type <span style='font-size: 12px; color: #292929; background-color: #f2f2f2;'>node send_push.js</span> in the terminal and wait for the notification to arrive in the mentioned Apple device.</p>
<p><a href='https://github.com/fedejordan/SimpleRTAppAPI'><span>Complete script for the push notification</span></a> service in check in the GitHub and is available for your reference.&nbsp;</p>
<p>It is a good practice to include a custom action with the notifications. It allows the user to communicate quickly with a proper preset response. Examples for custom actions include the ‘Reply’ or ‘Mark as read’ button in a message notification, ‘Install’ or ‘Snooze’ options in an OS update notification, etc. in our case, one easy and simple custom action would be ‘Retweet’.</p>
<p>Simple edits on the Node.js code shared above will enable these custom actions. Let’s see how to proceed.</p>
<p>While setting the <span style='font-size: 12px; color: #292929; background-color: #f2f2f2;'>notification</span> object, include below:</p>
<p><img src='https://lh5.googleusercontent.com/1_BcdX8WAm3OoJPTmZl701u0ZM-ALoXAamdvl-rpC4iaRkxzbL8NK9Y8A8qT8go3UHTqGiFx0yt1Au6km6LLuL4KlEVyToo-zHJ61sasmn4RBQjw8M5IL0ts3MNTd-DDC9Wbr78=s0' width='623' height='71' loading='lazy' alt='Ios notification object'></p>
<p>Also, to let the iOS app know it is an allowed action with the below code:</p>
<p><img src='https://lh5.googleusercontent.com/0_72kEE7PHcs2XcmHll7wuzZNgXiZMnKLvSLs9gIA955xn3PxW21cGyR7T3he5MRq1TA-mz-XkZ6swWI3JY_W4fAdbS1uhIVVmuiwrUtoFjeLu4irBwEGGjt3E8l3SAPDMwY96A=s0' width='624' height='148' loading='lazy' alt='IoS notification object'></p>
<p>Thus, for our <em>AppDelegate.swift</em>, the script would be as follows:</p>
<p><img src='https://lh6.googleusercontent.com/Qkie7ZVQ56xynL5k-WByEWoy0OaMuuGOGUsQhERdpOl4MpAmytjB4yHd_xNiKq4jnqNHfuQVRkIJw-GTmHvpLSJbLMRBCj7dR5WP_BKQIpPKCZKbwQvDGLTI9R8ZpWLTylQ5Be0=s0' width='624' height='532' loading='lazy' alt='AppDelegate.swift notification object'></p>
<p><img src='https://lh5.googleusercontent.com/eZoS38d_5sOnoNo_Btfcj1AWOf17TZfpAg2qqxvcpqDkbuGERVgUUXlv0EXOIZW4afbN5Nisp5CSSH7syylx13Omzu_dfQUmr432z9UhvAkXSqk47wtHdVMEkkofrLxhwnUJ1HQ=s0' width='624' height='504' loading='lazy' alt='AppDelegate.swift notification object'></p>
<p><img src='https://lh4.googleusercontent.com/pxxXQS5gKsQMYsDf_zC5fY_BYX1FsINT_r-WA8gsR_3VEEZqI-rSK8kg-QBWA7U13vG-7uDSnGXll7Ik46TdAXd-L9Aihc2_qeNz1zwfh-so3jO0TIl59WI_uZAGy1A6n7il9e8=s0' width='624' height='171' loading='lazy'></p>
<h3 style='font-weight: bold; font-size: 30px;'>Conclusion</h3>
<p>As we come to the end of this blog, we have discussed all the below points in detail&nbsp;</p>
<ul>
<li aria-level='1'>The remote notifications</li>
<li aria-level='1'>APNs</li>
<li aria-level='1'>Certificate creation</li>
<li aria-level='1'>Fetching Device tokens</li>
<li aria-level='1'>Node.js code for delivering push notification</li>
</ul>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/ios-push-notifications-via-apns/">Sending iOS Push Notifications via APNs</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Developers Guide To Scaling Rails Apps</title>
		<link>https://www.engineyard.com/blog/developers-guide-scale-rails-apps/</link>
		
		<dc:creator><![CDATA[Engine Yard Team]]></dc:creator>
		<pubDate>Mon, 27 Sep 2021 00:00:00 +0000</pubDate>
				<category><![CDATA[Ruby On Rails]]></category>
		<category><![CDATA[Ruby Application Deployment]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[ruby on rails web development]]></category>
		<guid isPermaLink="false">https://www.engineyard.com/developers-guide-scale-rails-apps/</guid>

					<description><![CDATA[<p>From Airbnb to Zendesk, a ton of really great apps were built using the Ruby programming language and the Rails web framework. Albeit a less popular option than other front-end frameworks such as React, Angular, and Vuejs, Rails still holds substantial merit in modern software development. Ruby on Rails (RoR) is open-source, well-documented, fiercely maintained, [&#8230;]</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/developers-guide-scale-rails-apps/">The Developers Guide To Scaling Rails Apps</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>From Airbnb to Zendesk, a ton of really great apps were built using the Ruby programming language and the Rails web framework. Albeit a less popular option than other front-end frameworks such as React, Angular, and Vuejs, Rails still holds substantial merit in modern software development.</p>
<p><span id="more-2085"></span></p>
<p>Ruby on Rails (RoR) is open-source, well-documented, fiercely maintained, and constantly extended with new Gems — community-created open-source libraries, serving as “shortcuts” for standardized configuration and distribution of Ruby code.</p>
<p><a href="https://rubygems.org/gems/rails/versions/4.2.6">Rails</a>&nbsp;is arguably the biggest RoR gem of them all — a full-stack server-side web application framework that is easy to customize and scale.</p>
<h2><strong>What is Rails? A Quick Refresher</strong></h2>
<p>Rails was built on the premises of Model-View-Controller (MVC) architecture.</p>
<p>This means each Rails app has three interconnected layers, accountable for a respective set of actions:</p>
<ol>
<li aria-level="1">Model:&nbsp;A data layer, housing the business logic of the app</li>
<li aria-level="1">Controller:&nbsp;The “brain center”, handling application functions</li>
<li aria-level="1">View: Defines graphical user interfaces (GUIs) and UI performance</li>
</ol>
<p>In essence, the model layer establishes the required data structure and contains codes needed to process the incoming data in HTML, PDF, XML, RSS, and other formats. The model layer then communicates updates to the View, which updates the GUI. The controller, in turn, interacts both with models and views. For instance, when receiving an update from a view, it notifies the model on how to process it. At the same time, it can update the view too on how to display the result for the user.</p>
<p><img loading="lazy" decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image1.png" sizes="auto, (max-width: 510px) 100vw, 510px" srcset="https://www.engineyard.com/wp-content/uploads/2022/02/image1.png 916w, https://www.engineyard.com/wp-content/uploads/2022/02/image1-300x146.png 300w, https://www.engineyard.com/wp-content/uploads/2022/02/image1-768x374.png 768w" alt="rails-architecture" width="510" height="248"></p>
<p>(Basic Rails app architecture. Image source:&nbsp;<a href="https://medium.com/the-renaissance-developer/ruby-on-rails-http-mvc-and-routes-f02215a46a84">Medium</a>)</p>
<p>The underlying MVC architecture lends several important advantages to Rails:</p>
<ul>
<li aria-level="1">Parallel development capabilities&nbsp;— one developer can work on View, while others handle the model subsystem. The above also makes Ruby on Rails a popular choice for rapid application development (RAD) methodology.</li>
<li aria-level="1">Reusable code components&nbsp;— controllers, views, and models can be packaged to share and reuse across several features with relative ease. When done right, this results in cleaner, more readable code, as well as faster development timelines. Also, Ruby on Rails is built on the DRY principle (don’t repeat yourself), prompting more frequent code reuse for monotonous functions.</li>
<li aria-level="1">Top security&nbsp;— the framework has a host of built-in security-centric features such as protection against SQL injections and XSS attacks, among others. Moreover, there’s plenty of community-shipped gems addressing an array of common and emerging cybersecurity threats.</li>
<li aria-level="1">Strong scalability potential&nbsp;—&nbsp;there’s a good reason why jumbo-sized web apps such as GitHub, Twitch, and Fiverr are built on Rails. Because it scales well when the overall app architecture and deployment strategy are done right. In fact, one of the oldest Rails apps, Shopify, scales to<a href="https://shopify.engineering/write-fast-code-ruby-rails">&nbsp;processing millions of requests per minute</a>&nbsp;(RPM).</li>
</ul>
<p>In spite of this, many Rails guides still make the arbitrary claim that&nbsp;<a href="https://www.engineyard.com/blog/5-tips-to-scale-your-ruby-on-rails-application/">Rails apps are hard to scale</a>. &nbsp;Are these true? Not entirely, as this post will showcase.</p>
<h2><strong>3 Common Problems With Scaling Rails Apps</strong></h2>
<p>The legacy lore once told that scaling Rails apps is like passing a camel through the eye of a needle — exasperating and exhausting.</p>
<p>To better understand where these concerns are coming from, let’s first recap what scalability is for web apps.</p>
<p>Scalability indicates the application’s architectural capability to handle more user requests per minute (RPM) in the future.</p>
<p>The keyword here is “architecture”, as your choices of infrastructure configuration, connectivity, and overall layout are determinants to the entire system’s ability to scale. The framework(s) or programming languages you use will only have a marginal (if any) impact on the scalability.</p>
<p>In the case of RoR, developers, in fact, get a slight advantage as the framework promotes clean, modular code that is easy to integrate with more database management systems. Moreover, adding&nbsp;<a href="https://www.devgraph.com/2020/10/09/what-is-a-load-balancer-definition-explanation/?utm_source=EngineYard">load balancers</a>&nbsp;for processing a higher number of requests is relatively easy too.</p>
<p>Yet, the above doesn’t fully eradicate scaling issues on Rails. Let’s keep it real: any app is hard to scale when the underlying infrastructure is subpar.</p>
<p>Specifically, Ruby scaling issues often pop up due to:</p>
<ul>
<li aria-level="1">Poor database querying</li>
<li aria-level="1">Inefficient indexing</li>
<li aria-level="1">Lack of logging and monitoring</li>
<li aria-level="1">Subpar database engine selection</li>
<li aria-level="1">Sluggish caching</li>
<li aria-level="1">Overly complex and spaghetti code</li>
</ul>
<h3><strong>Over-Engineered App Architecture</strong></h3>
<p>RoR supports multi-threading. This means the Rails framework can handle concurrent processing of different parts of code.</p>
<p>On the one hand, multi-threading is an advance since it enables you to use CPU time wiser and ship high-performance apps.</p>
<p>At the same time, however, the cost of context switching between different threads in highly complex apps can get high. Respectively, performance starts lagging at some point.</p>
<h4><i>How to Cope</i></h4>
<p>By default, Ruby on Rails prioritizes clean, reusable code. Making your Rails app architecture overly complex (think too custom) indeed can lead to performance and scalability issues.</p>
<p>This was the case with Twitter circa 2007.</p>
<p>The team developed a Twitter UI prototype on Rails and then decided to further code the back-end on Rails too. And they decided to build a fully custom, novel back-end from scratch rather than modifying some tested components. Unsurprisingly, their product behaved weirdly and times and scaling it was challenging, as the team admitted in a&nbsp;<a href="https://www.slideshare.net/Blaine/scaling-twitter/6-Its_Easy_Really1_Realize_Your">presentation</a>. They ended up with a ton of issues when partitioning databases because their code was overly complex and bloated.</p>
<p><img loading="lazy" decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/Untitled-design.jpg" sizes="auto, (max-width: 510px) 100vw, 510px" srcset="https://www.engineyard.com/wp-content/uploads/2022/02/Untitled-design.jpg 915w, https://www.engineyard.com/wp-content/uploads/2022/02/Untitled-design-300x112.jpg 300w, https://www.engineyard.com/wp-content/uploads/2022/02/Untitled-design-768x287.jpg 768w" alt="Twitter-UI-Prototype" width="510" height="191"></p>
<p>Image Source:&nbsp;<a href="https://www.slideshare.net/Blaine/scaling-twitter/28-MemCache">SlideShare</a></p>
<p>Interestingly, at the same time, another high-traffic Rails web app called Penny Arcade was doing just fine. Why? Because it had no funky overly-custom code, had clearly mapped dependencies, and hailed well with connected databases.</p>
<p>Remember: Ruby supports multi-processing within apps. In&nbsp;some cases,&nbsp;<a href="https://naturaily.com/blog/multiprocessing-in-ruby">multi-process apps</a>&nbsp;can perform better than multi-thread ones. But the trick with processes is that they consume more memory and have more complex dependencies. If you inadvertently kill a parent process, children processes will not get informed about the termination and thus, turn into&nbsp;sluggish “zombie” processes. This means they’ll keep running and consume resources. So watch out for those!</p>
<h3><strong>Suboptimal Database Setup</strong></h3>
<p>In the early days, Twitter had intensive write workloads and poorly organized read patterns, which were non-compatible with database sharding.</p>
<p>At present, a lot of Rails developers are still skimming on coding proper database indexes and triple-checking all queries for redundant requests. Slow database queries, lack of caching, and tangled database indexes can throw any good Rails app off the rails (pun intended).</p>
<p>Sometimes, complex database design is also part of deliberate decisions, as was the case with one of&nbsp;<a href="https://resources.engineyard.com/penny-pop-case-study?__hstc=246083099.e9b22777cc27c7816815e47174d1b163.1627448468612.1632460445279.1632717863167.52&amp;__hssc=246083099.2.1632717863167&amp;__hsfp=3286707902">our clients, PennyPop</a>. To store app data, the team set up an API request to the Rails application. The app itself then stores the data inside DynamoDB and sends a response back to the app. Instead of ActiveRecord, the team created their own data storage layer to enable communication between the app and DynamoDB.</p>
<p>But the issue they ran into is that DynamoDB has limits on how much information can be stored in one key. This was a technical deal-breaker, but the dev team came up with an interesting workaround — compressing the value of the key to a payload of base64 encoded data. Doing so has allowed the team to exchange bigger records between the app and the database without compromising the user experience or app performance.</p>
<p>Sure, the above operation requires more CPU. But since they are using&nbsp;<a href="https://www.engineyard.com/?__hstc=246083099.e9b22777cc27c7816815e47174d1b163.1627448468612.1632460445279.1632717863167.52&amp;__hssc=246083099.2.1632717863167&amp;__hsfp=3286707902">Engine Yard</a>&nbsp;to help manage and optimize other infrastructure, these costs remain manageable.</p>
<h4><i>How to Cope</i></h4>
<p>Granted, there are many approaches to improving Rails database performance. Deliberate caching and database partitioning (sharding) is one of the common routes as your app grows more complex.</p>
<p>What’s even better is that you have a ton of great solutions for resolving RoR database issues, such as:</p>
<ul>
<li aria-level="1">Redis&nbsp;— an open-source in-memory data structure store for Rails apps.</li>
<li aria-level="1">ActiveRecord&nbsp;— a database querying tool standardizing access to popular databases with built-in caching capabilities.</li>
<li aria-level="1">Memcached&nbsp;— distributed memory caching system for Ruby on Rails.</li>
</ul>
<p>The above three tools can help you sufficiently shape up your databases to tolerate extra-high loads.</p>
<p>Moreover, you can:</p>
<ul>
<li aria-level="1">Switch to UUIDs over standard IDs for principle keys as your databases grow more complex.</li>
<li aria-level="1">Try other ORM alternatives to ActiveRecord when your DBs get extra-large. Some good ones include Sequel, DataMapper, and ORM Adapter.</li>
<li aria-level="1">Use database profiling gems to diagnose and detect speed and performance issues early on. Popular ones are rack-mini-profiler, bullet, rails_panel, etc.</li>
</ul>
<h3><strong>Insufficient Server Bandwidth</strong></h3>
<p>The last problem is basic but still pervasive. You can’t accelerate your Rails apps to millions of RPMs if you lack resources.</p>
<p>Granted, with cloud computing, provisioning extra instances is a matter of several clicks. Yet, you still need to understand and account for:</p>
<ul>
<li aria-level="1">Specific apps/subsystems requirements for extra resources</li>
<li aria-level="1"><a href="https://www.devgraph.com/2021/05/26/cloud-cost-optimization-10-lessons-learned-from-scanning-45k-aws-accounts/">Cloud computing costs</a>&nbsp;(aka the monetary tradeoff for speed)</li>
</ul>
<p>Ideally, you need tools to constantly scan your systems and identify cases of slow performance, resources under (and over)-provisioning, as well as overall performance benchmarks for different apps.</p>
<p>Not having such is like driving without a speedometer: You rely on a hunch to determine if you are going too slow or deadly fast.</p>
<h4><i>How to Cope</i></h4>
<p>One of the&nbsp;<a href="https://www.engineyard.com/blog/10-lessons-learned-from-building-engine-yards-container-platform-on-kubernetes/">lessons we learned when building and scaling Engine Yard&nbsp;</a>on Kubernetes was that the container platform sets no default resource limits for hosted containers. Respectively, your apps can consume unlimited CPU and memory, which can create “noisy neighbor” situations, where some apps rack up too many resources and drag down the performance of others.<br />
The solution: Orchestrate your containers from the get-go. Use Kubernetes Scheduler to right-size nodes for the pods, limit maximum resource allocation, plus define pod preemption behavior.</p>
<p>Moreover, if you are running containers, always set up your own logging and monitoring&nbsp;since there are no out-of-the-box solutions available.&nbsp;Adding Log Aggregation to Kubernetes provides extra visibility into your apps’ behavior.</p>
<p>In our case, we use:</p>
<ul>
<li aria-level="1">Fluent Bit for distributed log collection</li>
<li aria-level="1">Kibana + Elasticsearch for log analysis</li>
<li aria-level="1">Prometheus + Grafana for metrics alerting and visualization</li>
</ul>
<p>To sum up:&nbsp;The key to ensuring scalability is weeding out the lagging modules and optimizing different infrastructure and architecture elements individually for a greater cumulative good.</p>
<h2><strong>Scaling Rails Apps: Two Main Approaches</strong></h2>
<p>Similar to others, Rails apps scale in two ways — vertically and horizontally.</p>
<p>Both approaches have their merit in respective cases.</p>
<h3><strong>Vertical Scaling</strong></h3>
<p>Vertical scaling, i.e., provisioning more server resources to an app, can increase the number of RPMs. The baseline premises are the same as for other frameworks. You add extra processors, RAM, etc., until it is technically feasible and makes financial sense. Understandably, vertical scaling is a temp “patch” solution.</p>
<p>Scaling Rails apps vertically makes sense to accommodate linear or predictable growth since cost control will be easy too. Also, vertical scaling is a good option for upgrading database servers. After all, slow databases can be majorly accelerated when placed on better hardware.</p>
<p>Hardware is the obvious limitation to vertical scaling. But even if you are using cloud resources, still scaling Rails apps vertically can be challenging.</p>
<p>For example, if you plan to implement Vertical Pod Autoscaling (VPA) on Kubernetes, it accounts for several limitations.</p>
<p>During our experiments with scaling Ruby apps, we found that:</p>
<ul>
<li aria-level="1">VPA is a rather disruptive method since it busts the original pod and then recreates its vertically scaled version. This can cause much havoc.</li>
<li aria-level="1">You cannot pair VPA with Horizontal Pod Autoscaling.</li>
</ul>
<p>So it’s best to prioritize horizontal scaling whenever you can.</p>
<h3><strong>Horizontal Scaling</strong></h3>
<p>Horizontal scaling, i.e., redistributing your workloads across multiple servers, is a more future-proof approach to scaling Rails apps.</p>
<p>In essence, you convert your apps in a three-tier architecture featuring:</p>
<ul>
<li aria-level="1">Web server and load balancer for connected apps</li>
<li aria-level="1">Rails app instances (on-premises or in the cloud)</li>
<li aria-level="1">Database instances (also local or cloud-based)</li>
</ul>
<p>The main idea is to distribute loads across different machines to obtain optimal performance equitably.</p>
<p>To effectively reroute Rails processes across server instances, you must select the optimal web server and load balancing solution. Then right-size instances to the newly decoupled workloads.</p>
<h4><i>Load balancing&nbsp;</i></h4>
<p>Load balancers are the key structural element for scale-out architecture. Essentially, they perform a routing function and help optimally distribute incoming traffic across connected instances.</p>
<p>Most cloud computing services come with native software load balancing solutions (think&nbsp;<a href="https://aws.amazon.com/elasticloadbalancing/">Elastic Load Balancing&nbsp;</a>on AWS). Such solutions also support dynamic host port mapping. This helps establish a seamless pairing between registered web balancers and container instances.</p>
<p>When it comes to Rails apps, the two most common options are using a combo of&nbsp;web servers&nbsp;and&nbsp;app servers&nbsp;(or a fusion service) to ensure optimal performance.</p>
<ul>
<li>Web servers transfer the user request to your website and then pass it to a Rails app (if applicable). Essentially, they filter out unnecessary requests for CSS, SSL, or JavaScript components (which the server can handle itself), thus reducing the number of requests to the Rails app to bare essentials.</li>
</ul>
<p>–&nbsp;Examples of Rails web servers:&nbsp;Ngnix&nbsp;and&nbsp;Apache.</p>
<ul>
<li>App servers are programs that maintain your app in memory. So that when an incoming request from a web server apps appears, it gets routed straight to the app for handling. Then the response is bounced back to the web server and, subsequently, the user. When paired with a web server in production, such a setup lets you render requests to multiple apps faster.</li>
</ul>
<p>–&nbsp;Examples of app servers for Rails:&nbsp;Unicorn, Puma, Thin, Rainbows.</p>
<p>Finally, there are also “fusion” services such as&nbsp;Passenger App&nbsp;(Phusion Passenger). This service integrates with popular web servers (Ngnix and Apache) and brings in an app server layer — available for standalone and combo use with web servers.</p>
<p><img loading="lazy" decoding="async" src="https://www.engineyard.com/wp-content/uploads/2022/02/image4.png" sizes="auto, (max-width: 510px) 100vw, 510px" srcset="https://www.engineyard.com/wp-content/uploads/2022/02/image4.png 700w, https://www.engineyard.com/wp-content/uploads/2022/02/image4-300x89.png 300w" alt="Phusion-Passenger" width="510" height="151"></p>
<p>Image Source:&nbsp;<a href="https://www.phusionpassenger.com/library/indepth/integration_modes.html">Phusion Passenger</a></p>
<p>Passenger is an excellent choice if you want to roll out unified app server settings for a bunch of apps in one go without fiddling with a separate app server setup for each.</p>
<p>In a nutshell, the main idea behind using web and app servers is to span different rails processes optimally across different instances.</p>
<p>Pro tip:&nbsp;What we found when building our product is that AWS Elastic Load Balancer often doesn’t suffice. A major drawback is that ELB can’t handle multiple vhosts.</p>
<p>In our case, we went on with configuring an NGINX-based load balancer and configured auto-scaling on it to support ELB. As an alternative, you can also try HAProxy.</p>
<h4><i>App Instances&nbsp;</i></h4>
<p>The next step of scale-out architecture is configuring communication between different app instances, where your Rails workloads will be allocated.</p>
<p>App servers (Unicorn, Puma, etc.) help ensure proper communication between web servers and subsequently increase the throughput of requests processed per second. On Rails, you can allocate an app server to handle multiple app instances, which in turn can have separate “worker” processes or threads (depending on which type of app server service you are using).</p>
<p>It’s important, however, to ensure that different app servers can communicate well with the webserver.&nbsp;Rack&nbsp;interface comes in handy here as it helps homogenize communication standards between standalone app servers.</p>
<p>When it comes to configuring the right instances for containers, keep in mind the following:</p>
<ol>
<li aria-level="1">You have four variables to min/max CPU and min/max memory to regulate pod size</li>
<li aria-level="1">Limit the resources using [minimum requirement + 20%] formula</li>
<li aria-level="1">Use average CPU utilization and average memory utilization as scaling metrics</li>
<li aria-level="1">Mind the timing. Pods and clusters take 4 to 12 minutes to scale up on Kubernetes.</li>
</ol>
<p>P.S. If you don’t want to do the above guesswork every time you are building a new pod/cluster, Engine Yard comes with a predictive cluster scaling feature, which helps you scale your infrastructure just-in-time without ballooning the costs.</p>
<h4><i>Database Scaling</i></h4>
<p>Transferring databases to a separate server, used by all app instances, is one of the sleekest moves you can do to&nbsp;<a href="https://www.engineyard.com/blog/5-tips-to-scale-your-ruby-on-rails-application/">scale Rails apps</a>.</p>
<p>First of all, this can be a nice exercise in segregating your data and implementing database replication for improving business continuity. Secondly, doing so can reduce the querying time since the request will not have to travel through multiple database instances where different bits of data are stored. Instead, it will go straight to a consolidated repository.</p>
<p>Thus, consider setting up a dedicated MySQL or PostgreSQL server for your relational databases. Then scrub them clean and ensure optimal instance size to save costs.</p>
<p>For example, AWS RDC lets you select among 18 types of database instances and codify fine-grain provisioning. Choosing to host your data in a cheaper cloud region can drive substantial cost savings (up to 40% at times!).</p>
<p>Here’s how on-demand hourly costs differ across AWS regions:</p>
<p>US East (Ohio)</p>
<ul>
<li aria-level="1">db.t3.small — $0.034 per hour</li>
<li aria-level="1">db.t3.xlarge — $0.272 per hour</li>
<li aria-level="1">db.t3.2xlarge — $0.544 per hour</li>
</ul>
<p>US West (LA)</p>
<ul>
<li aria-level="1">db.t3.small — $0.0408 per hour</li>
<li aria-level="1">db.t3.xlarge —$0.3264 per hour</li>
<li aria-level="1">db.t3.2xlarge — $0.6528 per hour</li>
</ul>
<p>Europe (Frankfurt)</p>
<ul>
<li aria-level="1">db.t3.small — $0.04 per hour</li>
<li aria-level="1">db.t3.large — $0.16 per hour</li>
<li aria-level="1">db.t3.2xlarge — $0.64 per hour</li>
</ul>
<p>Asia Pacific (Seoul)</p>
<ul>
<li aria-level="1">db.t3.small —$0.052 per hour</li>
<li aria-level="1">db.t3.large — $0.208 per hour</li>
<li aria-level="1">db.t3.2xlarge — $0.832 per hour</li>
</ul>
<p>Another pro tip: opt for reserved instances over on-demand when you can to further slash the hourly costs.</p>
<h4><i>Caching</i></h4>
<p>Database caching implementation is another core step to accelerating your Rails apps, especially when it comes to database performance. Given the fact that RoR comes with a native query caching feature that caches the result set returned by each query, it’s a shame not to profit from this!</p>
<p>Caching can help you speed up those slow queries. But prior to implementing, investigate!&nbsp;Once you’ve found the “offenders”, consider trying out&nbsp;<a href="https://guides.rubyonrails.org/caching_with_rails.html">different strategies</a>&nbsp;such as:</p>
<ul>
<li aria-level="1">Low-level caching&nbsp;— works best for any type of caching to retrieve database queries.</li>
<li aria-level="1">Redis cache store&nbsp;— lets you store keys and value pairs up to 512 MB in memory, plus provides native data replication.</li>
<li aria-level="1">Memcache store&nbsp;— another easy-to-implement in-memory datastore with values limited at 1 MB. Supports multi-thread architecture, unlike Redis.</li>
</ul>
<p>Ultimately, caching improves data availability and, by proxy, your application’s querying speed and performance.</p>
<h4><i>Database sharding</i></h4>
<p>Lastly, at some point in your database scaling journey, you’ll inevitably face the decision to shard your relational databases.</p>
<p>Data sharding means slicing your DB records horizontally or vertically into smaller chunks (shards) and storing them on a cluster of database nodes. The definitive advantage is that querying should now happen faster since a large database gets split in two and has twice more memory, I/O, and CPU to run.</p>
<p>The tradeoff, however, is that sharding can significantly affect your app’s logic. The scope of each query is now limited to either DB 1 or DB 2 — there’s no commingling. Respectively, when adding new app functions, you need to carefully consider how to access data across shards, how sharing relates to the infrastructure, and what’s the best way to scale out the supporting infrastructure without affecting the app’s logic.</p>
<h2><strong>To Conclude: Is There An Easier Solution to Scaling Rails Apps?</strong></h2>
<p>Scaling Rails apps is a careful balancing act of ensuring optimal instance allocation, timely resource, provisioning, and careful container orchestration. Keeping tabs on all the relevant metrics across a portfolio of apps and sub-services isn’t an easy task when done manually. And it shouldn’t be.</p>
<p>You can try Engine Yard Kontainers (EYK) — our&nbsp;<a href="https://support.cloud.engineyard.com/hc/en-us/articles/360058885853-Introduction-to-Engine-Yard-Kontainers?__hstc=246083099.e9b22777cc27c7816815e47174d1b163.1627448468612.1632460445279.1632717863167.52&amp;__hssc=246083099.2.1632717863167&amp;__hsfp=3286707902">NoOps PaaS autoscaling services</a>&nbsp;for containerized apps. In essence, we act as your invisible DevOps team. You code your apps and deploy them to EYK, and we take over auto-scaling implementation, container orchestration, and other infrastructure right-sizing tasks from there.</p>
<p>Learn more about&nbsp;<a href="https://www.engineyard.com/?__hstc=246083099.e9b22777cc27c7816815e47174d1b163.1627448468612.1632460445279.1632717863167.52&amp;__hssc=246083099.2.1632717863167&amp;__hsfp=3286707902">Engine Yard</a>.</p>
<p>The post <a rel="nofollow" href="https://www.engineyard.com/blog/developers-guide-scale-rails-apps/">The Developers Guide To Scaling Rails Apps</a> appeared first on <a rel="nofollow" href="https://www.engineyard.com">EngineYard</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
