<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0"><channel><title>Pulumi Blog: Developer experience</title><link>https://www.pulumi.com/blog/tag/developer-experience/</link><description>Pulumi blog posts: Developer experience.</description><language>en-us</language><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><item><title>Treating Prompts Like Code: A Content Engineer's AI Workflow</title><link>https://www.pulumi.com/blog/treating-prompts-like-code/</link><pubDate>Mon, 09 Mar 2026 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/treating-prompts-like-code/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/treating-prompts-like-code/index.png" /&gt;
&lt;p&gt;Pulumi has a lot of engineers. It has marketers, solution architects, developer advocates. Everyone has something to contribute to docs and blog posts — domain expertise, hard-won lessons, real-world examples. What they don&amp;rsquo;t all have is familiarity with our &lt;a href="https://gohugo.io"&gt;Hugo&lt;/a&gt; setup, our style guide, our metadata conventions, or where a new document is supposed to live in the navigation tree. I joined Pulumi in July 2025 as a Senior Technical Content Engineer. A few weeks in, my sole teammate departed. The docs practice was now, functionally, me.&lt;/p&gt;
&lt;p&gt;The problem was clear enough: how do you take one docs engineer&amp;rsquo;s accumulated knowledge and make it available to everyone who needs it, without that engineer becoming a bottleneck?&lt;/p&gt;
&lt;p&gt;I started packaging it. Here&amp;rsquo;s what that looked like in practice.&lt;/p&gt;
&lt;h2 id="the-real-problem-ai-solves"&gt;The real problem AI solves&lt;/h2&gt;
&lt;p&gt;Everyone talks about AI making you faster. That&amp;rsquo;s not wrong, but it&amp;rsquo;s not the most interesting part — at least not for me.&lt;/p&gt;
&lt;p&gt;The most interesting part is what it does to the &lt;em&gt;starting&lt;/em&gt; problem. I have an ADHD brain (not formally diagnosed, but with enough self-recognition to know what&amp;rsquo;s going on). I know what that means for my relationship with most tasks: I can see the problem, I understand it, I want to fix it, and then the sheer weight of starting crushes me flat.&lt;/p&gt;
&lt;p&gt;When I&amp;rsquo;m stuck on a task, the issue is almost never that I don&amp;rsquo;t know what to do. It&amp;rsquo;s that my brain is trying to hold the entire finished product in working memory while simultaneously producing the first step. That&amp;rsquo;s an enormous cognitive tax, and for an ADHD brain it&amp;rsquo;s often insurmountable.&lt;/p&gt;
&lt;p&gt;Talking through a problem conversationally is a completely different cognitive load. I can tell &lt;a href="https://claude.ai"&gt;Claude&lt;/a&gt; &amp;ldquo;here&amp;rsquo;s the issue, here&amp;rsquo;s what I&amp;rsquo;m trying to accomplish, here&amp;rsquo;s what&amp;rsquo;s weird about it,&amp;rdquo; and suddenly I&amp;rsquo;m not staring at a blank page anymore. I&amp;rsquo;m in a conversation. The scaffold exists. I can build on it.&lt;/p&gt;
&lt;p&gt;That dynamic isn&amp;rsquo;t new for me. In a previous role writing training modules at Microsoft, I did some of my best work, not because the work was easy, but because I had a collaborator. A friend to think out loud with. Someone to say &amp;ldquo;okay, so what are we actually trying to say here?&amp;rdquo; That conversational scaffolding was the difference between spinning and shipping.&lt;/p&gt;
&lt;p&gt;In my current role as a team of one, AI turned out to be that collaborator.&lt;/p&gt;
&lt;p&gt;This isn&amp;rsquo;t really a productivity story. It&amp;rsquo;s closer to a cognitive accommodation story. And I&amp;rsquo;d bet a lot of people — diagnosed or not — will recognize what I&amp;rsquo;m describing.&lt;/p&gt;
&lt;h2 id="treating-prompts-like-code"&gt;Treating prompts like code&lt;/h2&gt;
&lt;p&gt;If conversational scaffolding could lower my own activation energy, the next question was obvious: could I build that for anyone who needed it? I knew I wanted to use AI to solve this problem, but I didn&amp;rsquo;t want to just write a bunch of one-off prompts. That would be a maintenance nightmare, and it wouldn&amp;rsquo;t scale beyond me. I needed a system. Claude Code calls these reusable prompts &lt;em&gt;skills&lt;/em&gt; — other platforms have the same idea under names like plugins or extensions. My first real experiment was &lt;code&gt;/docs-review&lt;/code&gt; — a reusable prompt that would run my writing through a consistent set of criteria before I committed it. Nothing fancy. I just wanted a reliable bar that didn&amp;rsquo;t depend on my mood or how much coffee I&amp;rsquo;d had.&lt;/p&gt;
&lt;p&gt;Then it occurred to me: every PR to our docs repo should get this automatically. So I wired it into our CI/CD pipeline. Meagan, my manager, loved it — and after a few weeks, she noticed that PR quality had improved dramatically. On almost every PR, contributors were now spontaneously pushing an &amp;ldquo;Addressing feedback&amp;rdquo; commit right after the automated review posts — catching and fixing issues before I ever saw the PR.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s when something clicked: I wasn&amp;rsquo;t writing prompts anymore. I was writing &lt;em&gt;modules&lt;/em&gt; — reusable, composable pieces of my own expertise.&lt;/p&gt;
&lt;p&gt;The insight was straightforward, but it changed how I thought about the whole system: if multiple skills need the same context — our style guide, our review criteria, our content standards — that context should live in one place and get consumed by everything that needs it. Just like a shared library. Just like any decent software project.&lt;/p&gt;
&lt;p&gt;I created a &lt;code&gt;REVIEW-CRITERIA.md&lt;/code&gt; file as the single source of truth for what a &amp;ldquo;good&amp;rdquo; docs PR review looks like at Pulumi. Every skill that does any kind of review pulls from it. Change it once, and everything gets smarter at once. Likewise with our style guide, our Hugo conventions, our navigation structure. All of that lives in central reference files that any skill can pull from. If something changes, I change it in one place and all the skills get the update.&lt;/p&gt;
&lt;p&gt;This also matters for token efficiency — which sounds like a nerdy footnote but isn&amp;rsquo;t, especially when automated reviews are running on every PR. Duplicating context across skills bloats token usage fast. Modularizing keeps it lean. Your CI/CD pipeline doesn&amp;rsquo;t care about elegance, but it definitely cares about cost.&lt;/p&gt;
&lt;p&gt;The mental model I kept coming back to: &lt;strong&gt;Don&amp;rsquo;t Repeat Yourself.&lt;/strong&gt; It&amp;rsquo;s the same principle that makes good software maintainable. It turns out it makes good AI workflows maintainable too.&lt;/p&gt;
&lt;h2 id="the-skill-catalog"&gt;The skill catalog&lt;/h2&gt;
&lt;p&gt;From there, the system grew organically. Whenever I found myself doing something more than once, I asked: &amp;ldquo;Can I turn this into a skill?&amp;rdquo; Here&amp;rsquo;s a sampling of what that produced:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/fix-issue&lt;/code&gt;&lt;/strong&gt; — takes a &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt; issue and recommends a concrete plan of attack, so I go from &amp;ldquo;here&amp;rsquo;s a ticket&amp;rdquo; to &amp;ldquo;here&amp;rsquo;s what I&amp;rsquo;m doing&amp;rdquo; without the spinning-up tax.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/shipit&lt;/code&gt;&lt;/strong&gt; — runs pre-commit checks, writes a focused commit message, and drafts a PR description.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/pr-review&lt;/code&gt;&lt;/strong&gt; — full doc review on a PR branch: style guide, code examples, screenshots, optional test deployment, then an Approve/Merge/Request Changes dialog with a drafted comment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/slack-to-issue&lt;/code&gt;&lt;/strong&gt; — converts &lt;code&gt;#docs&lt;/code&gt; &lt;a href="https://slack.com"&gt;Slack&lt;/a&gt; conversations into properly formed GitHub issues. Slack is where decisions happen; issues are where work gets tracked.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/glow-up&lt;/code&gt;&lt;/strong&gt; — runs an older doc through the modern style guide and flags outdated screenshots, for digging out of accumulated technical debt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/new-doc&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;/new-blog-post&lt;/code&gt;&lt;/strong&gt; — guide anyone through adding a new document or blog post with the right location, metadata, and navigation wiring. Engineers, marketers, whoever. The barrier to contributing just dropped significantly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;/docs-tools&lt;/code&gt;&lt;/strong&gt; — helps other repo users discover that any of this exists. Discoverability is a real problem with internal tooling.&lt;/p&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Slack&amp;rsquo;s built-in Claude integration isn&amp;rsquo;t the same Claude running your Claude Code workflows — they don&amp;rsquo;t share context or custom instructions. If you want consistent criteria across both surfaces, you need to bring your own backend. That&amp;rsquo;s exactly what &lt;code&gt;/slack-to-issue&lt;/code&gt; handles.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Other people started contributing skills to the repo — not because I asked, but because the pattern was legible enough to extend. Someone built a skill for SEO analysis. Marketing added their own review criteria. Engineers contributed workflows I never would have thought to build.&lt;/p&gt;
&lt;p&gt;The thing I&amp;rsquo;d built as a personal survival tool had become a shared platform. That happened because I treated the prompts like code: modular, reusable, documented, open for contribution.&lt;/p&gt;
&lt;h2 id="honest-limitations"&gt;Honest limitations&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s not a replacement for human judgment. These are probabilistic tools — they&amp;rsquo;re right most of the time, not all of the time. &lt;code&gt;/pr-review&lt;/code&gt; doesn&amp;rsquo;t approve PRs autonomously. It highlights things and then asks me, the human, to read them and make the call. The AI does the first pass; I do the last one. That&amp;rsquo;s not a workaround for a limitation — that&amp;rsquo;s the design.&lt;/p&gt;
&lt;p&gt;The system isn&amp;rsquo;t finished, either. It&amp;rsquo;s probably never finished. I&amp;rsquo;m still tweaking review criteria, still finding edge cases where a skill produces something weird, still adding new tools as new pain points emerge. Treating prompts like code means treating them like software: you ship, you iterate, you maintain. There&amp;rsquo;s no version 1.0 and done.&lt;/p&gt;
&lt;p&gt;And the ADHD angle is real but it&amp;rsquo;s not magic. There are still days where the paralysis wins. AI lowers the activation energy for starting; it doesn&amp;rsquo;t eliminate it. I&amp;rsquo;m still the one who has to show up. I suppose I could automate that too, but then we&amp;rsquo;d be in a whole different kind of dystopia.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Turn your workflows into skills&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Pulumi&amp;rsquo;s Agent Skills bring the same modular approach to infrastructure, teaching your coding agent the conventions your team relies on.&lt;/div&gt;
&lt;a href="https://www.pulumi.com/docs/ai/skills/" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="lessons-to-share"&gt;Lessons to share&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Know your models and their costs.&lt;/strong&gt; At Pulumi we primarily use Claude, and I work in &lt;a href="https://claude.ai/claude-code"&gt;Claude Code&lt;/a&gt;; for most tasks I reach for Sonnet rather than Opus. Opus is excellent, but it&amp;rsquo;s significantly more expensive, and well-crafted instructions to Sonnet handle the vast majority of my work just as effectively.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Treat it like a coworker.&lt;/strong&gt; Don&amp;rsquo;t just issue commands and wait for output. Ask what it thinks. Push back when it&amp;rsquo;s wrong. Explain your reasoning. The more you engage conversationally, the better the results tend to be. That extends to alignment, too — before diving into a complex task, talk through the approach first. A few minutes of alignment up front beats iterating on a misunderstood spec. I&amp;rsquo;ve gone as far as adding personal instructions to my config — things like playing along when I&amp;rsquo;m pretending to be Captain Picard, or using colorful language when the context calls for it. (Yes, those are literal config settings.) That sounds frivolous, but it isn&amp;rsquo;t: a tool you actually enjoy using is a tool you&amp;rsquo;ll reach for instead of avoid.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Modularize your workflow.&lt;/strong&gt; Don&amp;rsquo;t write one giant monolithic prompt that tries to do everything. Break it into focused skills that do one thing well and share common context through a central reference file. Easier to maintain, easier to debug, cheaper to run.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Version control your prompts.&lt;/strong&gt; Your skills are code. Treat them like code. Commit them, review them, iterate on them. If a skill starts producing weird output after a tweak, you&amp;rsquo;ll want to know what changed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Think about token burn rate.&lt;/strong&gt; This matters most when running automation in CI/CD. Keep your skills focused — a skill that checks style doesn&amp;rsquo;t need to load your Hugo navigation conventions. The model only reads what you give it, so give it only what it needs.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not everything needs to be a prompt.&lt;/strong&gt; This one is underappreciated: skills can include scripts, and that&amp;rsquo;s often the right call. When my team moves a doc in the repo, it needs to happen via &lt;code&gt;git mv&lt;/code&gt; to preserve history, and we need to add a redirect alias to the front matter to prevent 404s and protect SEO. That&amp;rsquo;s not something I want an AI to reason through from scratch every time — it&amp;rsquo;s a solved problem. So it&amp;rsquo;s a script. The skill just knows the script exists and what it does. Claude orchestrates; the script executes. That&amp;rsquo;s a cleaner, more reliable division of labor than asking an LLM to reinvent the wheel on every run.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not everything needs to be generative.&lt;/strong&gt; Corollary to the last point: if you need deterministic output, don&amp;rsquo;t use probabilistic tools. We have a skill that generates the meta image for blog posts — procedurally, not generatively. No AI-generated imagery. We have a brand to protect, and &amp;ldquo;let the AI vibe it out&amp;rdquo; isn&amp;rsquo;t a content strategy. The skill follows our visual standards programmatically and produces something consistent every time. Know what you&amp;rsquo;re automating and why.&lt;/p&gt;
&lt;h2 id="whats-next"&gt;What&amp;rsquo;s next&lt;/h2&gt;
&lt;p&gt;The next frontier is bringing some of this tooling to the less technical members of the team — marketing, in particular. The skills I&amp;rsquo;ve built assume a certain comfort level with terminals and repos. That&amp;rsquo;s fine for engineers. It&amp;rsquo;s a barrier for everyone else. A friendly interface would lower that bar significantly — that&amp;rsquo;s the direction I&amp;rsquo;m currently exploring.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a technical writer, a developer advocate, or a solo practitioner figuring out how AI fits into your workflow, the approach described here is a solid starting point. The tools matter, but the mental model matters more: treat your prompts like code. Make them reusable. Document them. Share them.&lt;/p&gt;
&lt;p&gt;Our &lt;a href="https://github.com/pulumi/docs"&gt;docs repo&lt;/a&gt; is public, so the skills are there for anyone who wants them. If you&amp;rsquo;re building something similar, steal freely — or contribute back.&lt;/p&gt;
&lt;p&gt;The blank page is still there. It&amp;rsquo;s just a lot less intimidating when you&amp;rsquo;ve got a good collaborator and a solid set of tools.&lt;/p&gt;
&lt;a
href="https://github.com/pulumi/docs/tree/master/.claude/commands"
class="btn btn-primary"
target="_blank"
rel="noopener noreferrer"
&gt;
See our docs skills for inspiration
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular text-sm ml-2" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-arrow-square-out-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;</description><author>Cam Soper</author><category>ai</category><category>automation</category><category>developer-experience</category></item><item><title>Golden Paths in IDPs: A Complete Guide to Reusable Infrastructure with Pulumi Components and Templates</title><link>https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/</link><pubDate>Wed, 20 Aug 2025 10:00:00 +0200</pubDate><guid>https://www.pulumi.com/blog/golden-paths-infrastructure-components-and-templates/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/golden-paths-infrastructure-components-and-templates/index.png" /&gt;
&lt;p&gt;Welcome to the second post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series. In this article, we explore how to create &lt;strong&gt;golden paths&lt;/strong&gt;, pre-architected, reusable infrastructure patterns that help standardize and accelerate cloud development.&lt;/p&gt;
&lt;p&gt;Modern cloud platforms offer endless options, over 200 AWS services, sprawling Azure catalogs, and countless DevOps tools. The result? Developers face decision fatigue and inconsistent implementations. Golden paths solve this by providing &lt;strong&gt;ready-to-use, production-grade infrastructure&lt;/strong&gt; that encodes your organization’s best practices, security policies, and operational standards.&lt;/p&gt;
&lt;p&gt;In this guide, you&amp;rsquo;ll learn how to build golden paths for your Internal Developer Platform using two core Pulumi constructs: &lt;strong&gt;Components&lt;/strong&gt;, reusable infrastructure building blocks, and &lt;strong&gt;Templates&lt;/strong&gt;, predefined, deployable patterns. You&amp;rsquo;ll see how to create infrastructure abstractions that are written once, shared across teams, and consumed in any language, turning weeks of setup into minutes of developer-ready infrastructure.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;The complete code examples from this post are available on &lt;a href="https://github.com/pulumi/workshops/tree/main/golden-paths-infrastructure-components-and-templates"&gt;GitHub&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-platform-engineering-layer-cake-a-model-for-idps"&gt;The Platform Engineering Layer Cake: A Model for IDPs&lt;/h2&gt;
&lt;p&gt;To understand where golden paths fit into an Internal Developer Platform (IDP), think in layers. This three-tier model structures your platform to deliver increasing levels of abstraction, reuse, and developer value:&lt;/p&gt;
&lt;h3 id="layer-1-infrastructure-layer"&gt;Layer 1: Infrastructure Layer&lt;/h3&gt;
&lt;p&gt;This is the foundation: raw cloud resources include VMs, databases, networks, and storage, which are the fundamental building blocks from AWS, Azure, GCP, and other providers. Pulumi gives you programmatic access to these resources through &lt;a href="https://www.pulumi.com/registry/"&gt;native providers&lt;/a&gt;, but working at this level requires deep infrastructure knowledge.&lt;/p&gt;
&lt;h3 id="layer-2-platform-layer---components"&gt;Layer 2: Platform Layer - Components&lt;/h3&gt;
&lt;p&gt;This is where the magic happens. &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components&lt;/a&gt; take those raw resources and package them into higher-level abstractions. Instead of manually configuring 20+ AWS resources for a secure web application, you create a component that handles all that complexity and exposes just the configuration that matters:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SecureWebApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.medium&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;minReplicas&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;maxReplicas&lt;/span&gt;: &lt;span class="kt"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;enableWAF&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;production&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="part-1-building-reusable-infrastructure-components"&gt;Part 1: Building Reusable Infrastructure Components&lt;/h2&gt;
&lt;p&gt;Reusable infrastructure components act as the foundation of your platform. They encapsulate complexity while remaining composable and scalable. Let&amp;rsquo;s build a real-world example: a component that deploys containerized microservices to AWS Fargate.&lt;/p&gt;
&lt;h3 id="the-power-of-multi-language-components"&gt;The Power of Multi-Language Components&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s what makes Pulumi components revolutionary: &lt;strong&gt;write once, consume anywhere&lt;/strong&gt;. Your platform team can author components in TypeScript, but application teams can consume them in Python, Go, .NET, Java, or even YAML. This separation of concerns is crucial for scaling platform engineering across diverse teams.&lt;/p&gt;
&lt;h3 id="building-a-microservice-component-step-by-step"&gt;Building a Microservice Component Step-by-Step&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s create a component that encapsulates everything needed to deploy a production-ready microservice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// microservice-component.ts
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/aws&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/awsx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appPath&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Path to application code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cpu?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// CPU units (256, 512, 1024, etc.)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memory?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Memory in MB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Application port
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;desiredCount?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Number of tasks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceComponent&lt;/span&gt; &lt;span class="kr"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentResource&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;serviceName&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="kr"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;clusterName&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.Output&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;: &lt;span class="kt"&gt;MicroserviceArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;opts?&lt;/span&gt;: &lt;span class="kt"&gt;pulumi.ComponentResourceOptions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;custom:infrastructure:Microservice&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="nx"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Set defaults
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cpu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cpu&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memory&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;desiredCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desiredCount&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create ECR repository for Docker images
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-repo`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;forceDelete&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Build and push Docker image
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-image`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;repositoryUrl&lt;/span&gt;: &lt;span class="kt"&gt;repository.url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;context&lt;/span&gt;: &lt;span class="kt"&gt;args.appPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;linux/amd64&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create Application Load Balancer
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadBalancer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ApplicationLoadBalancer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-lb`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;defaultTargetGroup&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HTTP&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;interval&lt;/span&gt;: &lt;span class="kt"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;timeout&lt;/span&gt;: &lt;span class="kt"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;healthyThreshold&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;unhealthyThreshold&lt;/span&gt;: &lt;span class="kt"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create ECS cluster
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cluster&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-cluster`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Create Fargate service
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;awsx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ecs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FargateService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;-service`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;: &lt;span class="kt"&gt;cluster.arn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;taskDefinitionArgs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;name&lt;/span&gt;: &lt;span class="kt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;image&lt;/span&gt;: &lt;span class="kt"&gt;image.imageUri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;cpu&lt;/span&gt;: &lt;span class="kt"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;memory&lt;/span&gt;: &lt;span class="kt"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;essential&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;portMappings&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;containerPort&lt;/span&gt;: &lt;span class="kt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;targetGroup&lt;/span&gt;: &lt;span class="kt"&gt;loadBalancer.defaultTargetGroup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;desiredCount&lt;/span&gt;: &lt;span class="kt"&gt;desiredCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;assignPublicIp&lt;/span&gt;: &lt;span class="kt"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;parent&lt;/span&gt;: &lt;span class="kt"&gt;this&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Export outputs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;interpolate&lt;/span&gt;&lt;span class="sb"&gt;`http://&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loadBalancer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loadBalancer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dnsName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;serviceName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clusterName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Register outputs
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;registerOutputs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;url&lt;/span&gt;: &lt;span class="kt"&gt;this.url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;serviceName&lt;/span&gt;: &lt;span class="kt"&gt;this.serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;clusterName&lt;/span&gt;: &lt;span class="kt"&gt;this.clusterName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="documenting-for-discoverability-and-adoption"&gt;Documenting for Discoverability and Adoption&lt;/h3&gt;
&lt;p&gt;To make your component easy to use, add comprehensive documentation and examples to a &lt;code&gt;README.md&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# MicroserviceComponent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Abstraction &lt;span class="k"&gt;for&lt;/span&gt; resources needed when using AWS container services.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A component to abstract the details related to:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Creating a docker image and pushing it to AWS ECR.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- Deploy to ECS Fargate using the docker image.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Inputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* appPath: Path to &lt;span class="nb"&gt;local&lt;/span&gt; folder containing the app and Dockerfile.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* port: Port to expose via an ALB.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* cpu &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: CPU capacity. Defaults to &lt;span class="m"&gt;256&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;i.e. 0.25 vCPU&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* memory &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: Memory capacity. Defaults to &lt;span class="m"&gt;512&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;i.e. 0.5GB&lt;span class="o"&gt;)&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* containerName &lt;span class="o"&gt;(&lt;/span&gt;Optional&lt;span class="o"&gt;)&lt;/span&gt;: Name of the container. Defaults to &lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Outputs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;* publicUrl: The DNS name &lt;span class="k"&gt;for&lt;/span&gt; the loadbalancer fronting the app.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Usage&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;## Specify Package in `Pulumi.yaml`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Add the following to your &lt;span class="sb"&gt;`&lt;/span&gt;Pulumi.yaml&lt;span class="sb"&gt;`&lt;/span&gt; file:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Note: If no version is specified, the latest version will be used.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;... omit &lt;span class="k"&gt;for&lt;/span&gt; brevity ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This documentation will help developers understand how to use your component effectively, including required inputs, outputs, and example usage.&lt;/p&gt;
&lt;h3 id="publishing-your-component-via-private-registry"&gt;Publishing Your Component via Private Registry&lt;/h3&gt;
&lt;p&gt;Once your component is ready, publish it to your &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;Pulumi Private Registry&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Tag your component version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git tag v1.0.1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Publish to your organization&amp;#39;s registry&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi package publish https://registry.pulumi.com/myorg/microservice-component
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now any team in your organization can discover and use your component, regardless of their language preference. All they need is to navigate to the &lt;code&gt;Components&lt;/code&gt; section in the Pulumi IDP and search for &lt;code&gt;microservice-component&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_components_view.png" alt="img_2.png"&gt;&lt;/p&gt;
&lt;h2 id="part-2-from-building-blocks-to-golden-paths"&gt;Part 2: From Building Blocks to Golden Paths&lt;/h2&gt;
&lt;p&gt;While components are powerful, they&amp;rsquo;re just the starting point. Golden path templates layer on opinionated scaffolding, workflows, and compliance best practices that guide developers to production.&lt;/p&gt;
&lt;h3 id="golden-path-maturity-from-zero-to-product-grade-platforms"&gt;Golden Path Maturity: From Zero to Product-Grade Platforms&lt;/h3&gt;
&lt;p&gt;Teams evolve from ad hoc deployments to mature, productized templates with versioning, metrics, and governance. These maturity levels reflect how deeply your platform enables safe, consistent delivery.&lt;/p&gt;
&lt;p&gt;&lt;img src="golden_paths_maturity_level.png" alt="img_8.png"&gt;&lt;/p&gt;
&lt;p&gt;Organizations typically progress through three stages of golden path maturity:&lt;/p&gt;
&lt;h4 id="stage-1-no-golden-paths"&gt;Stage 1: No Golden Paths&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Every team reinvents the wheel&lt;/li&gt;
&lt;li&gt;Inconsistent practices across projects&lt;/li&gt;
&lt;li&gt;High cognitive load on developers&lt;/li&gt;
&lt;li&gt;Security and compliance gaps&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="stage-2-dawn-of-templates"&gt;Stage 2: Dawn of Templates&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Basic cookie-cutter templates emerge&lt;/li&gt;
&lt;li&gt;Some standardization begins&lt;/li&gt;
&lt;li&gt;Manual processes still dominate&lt;/li&gt;
&lt;li&gt;Limited support and evolution&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="stage-3-templates-as-products"&gt;Stage 3: Templates as Products&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Golden paths have dedicated owners&lt;/li&gt;
&lt;li&gt;Regular release cycles and versioning&lt;/li&gt;
&lt;li&gt;Migration guides for updates&lt;/li&gt;
&lt;li&gt;Metrics track adoption and success&lt;/li&gt;
&lt;li&gt;Continuous improvement based on feedback&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="what-makes-a-golden-path-golden"&gt;What Makes a Golden Path Golden?&lt;/h3&gt;
&lt;p&gt;Drawing from &lt;a href="https://engineering.atspotify.com/2020/08/how-we-use-golden-paths-to-solve-fragmentation-in-our-software-ecosystem/"&gt;Spotify&amp;rsquo;s pioneering work&lt;/a&gt;, golden paths share these characteristics:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pre-architected and Supported&lt;/strong&gt;: The platform team owns and supports the path&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optional but Recommended&lt;/strong&gt;: Developers can deviate, but staying on the path ensures support&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transparent Abstractions&lt;/strong&gt;: The implementation is visible, not a black box&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensible&lt;/strong&gt;: Teams can add project-specific resources without breaking the pattern&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evolutionary&lt;/strong&gt;: Templates improve based on feedback and new requirements&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="building-a-go-microservice-golden-path"&gt;Building a Go Microservice Golden Path&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s create a complete golden path for Go microservices that includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Application scaffolding with best practices&lt;/li&gt;
&lt;li&gt;Infrastructure deployment using our component&lt;/li&gt;
&lt;li&gt;CI/CD pipeline configuration&lt;/li&gt;
&lt;li&gt;Observability setup&lt;/li&gt;
&lt;li&gt;Security controls&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="step-1-template-structure"&gt;Step 1: Template Structure&lt;/h4&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;go-microservice-boilerplate/
├── Pulumi.yaml # Infrastructure definition
├── src/ # Application code
│ ├── main.go # Go microservice
│ ├── Dockerfile # Container definition
│ └── go.mod # Dependencies
└── README.md # Documentation
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="step-2-application-scaffolding"&gt;Step 2: Application Scaffolding&lt;/h4&gt;
&lt;p&gt;The &lt;code&gt;src/main.go&lt;/code&gt; file contains a minimal Go microservice with all the best practices and compliance guardrails baked in. This helps developers to quickly get started and extend the application without worrying too much about selecting the right libraries or frameworks.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// source/main.go&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;context&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;flag&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;net/http&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;os/signal&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/labstack/echo/v4&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;github.com/labstack/echo/v4/middleware&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/sdk/resource&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/sdk/trace&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;go.opentelemetry.io/otel/semconv/v1.34.0&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;initTracer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TracerProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;otlptracehttp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewWithAttributes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SchemaURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServiceNameKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;semconv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ServiceVersionKey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;1.0.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewTracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithBatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;exporter&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithSampler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sdktrace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AlwaysSample&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;otel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetTracerProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;echoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueryParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello from Go microservice!&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;echo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;UTC&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RFC3339&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;healthHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;healthy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;health-check&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Run health check and exit&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;healthCheck&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://localhost:8080/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusCode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StatusOK&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;initTracer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Recover&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CORS&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;otelecho&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;${PROJECT}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/echo&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;echoHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GET&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/health&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;healthHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;:8080&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ErrServerClosed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;shutting down the server&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;chan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Interrupt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="nx"&gt;quit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cancel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WithTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Background&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;defer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-3-infrastructure-template-with-yaml"&gt;Step 3: Infrastructure Template with YAML&lt;/h4&gt;
&lt;p&gt;Here&amp;rsquo;s how you define the infrastructure using Pulumi YAML. You can instantly spot one of the features of Pulumi Components. We consume the &lt;code&gt;micorservice-component&lt;/code&gt; in YAML without knowing that it was authored in a different language. This is the power of Pulumi Components: write once, consume anywhere.&lt;/p&gt;
&lt;p&gt;And we see another feature of Pulumi Components: As it is a first-class citizen, we can embed the component and add additional resources like auto-scaling policies, alarms, and more directly in the YAML file. This allows us to create a complete golden path for deploying Go microservices on AWS ECS with auto-scaling capabilities.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${DESCRIPTION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;packages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;component-microservice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;https://github.com/smithrobs/component-microservice@v1.0.1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;A template for deploying a Go microservice on AWS ECS with auto-scaling capabilities.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;microserviceComponent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;component-microservice:MicroserviceComponent&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;appPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;./src&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;containerName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Target&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_target&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;maxCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;minCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service/${microserviceComponent.clusterName}/${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs:service:DesiredCount&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsPolicyUP&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Policy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_up&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_up&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;StepScaling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.resourceId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.scalableDimension}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.serviceNamespace}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepScalingPolicyConfiguration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;adjustmentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ChangeInCapacity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cooldown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricAggregationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Maximum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepAdjustments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;metricIntervalUpperBound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalingAdjustment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ecsPolicyDown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:appautoscaling:Policy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_down&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ecs_policy_down&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;policyType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;StepScaling&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;resourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.resourceId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalableDimension&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.scalableDimension}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceNamespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${ecsTarget.serviceNamespace}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepScalingPolicyConfiguration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;adjustmentType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ChangeInCapacity&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cooldown&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricAggregationType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Maximum&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;stepAdjustments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;metricIntervalLowerBound&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;scalingAdjustment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceCPUHighUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:cloudwatch:MetricAlarm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_high_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_high_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;comparisonOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;GreaterThanOrEqualToThreshold&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluationPeriods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CPUUtilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AWS/ECS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;statistic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Average&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alarmActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${ecsPolicyUP.arn}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ClusterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.clusterName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ServiceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;serviceCPULowUtilization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;aws:cloudwatch:MetricAlarm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_low_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;service_cpu_low_utilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;comparisonOperator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;LessThanOrEqualToThreshold&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;evaluationPeriods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;metricName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;CPUUtilization&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;AWS/ECS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;period&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;statistic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Average&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;alarmActions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;${ecsPolicyDown.arn}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;dimensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ClusterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.clusterName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ServiceName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.serviceName}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;publicUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${microserviceComponent.publicUrl}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="step-4-documentation-and-examples"&gt;Step 4: Documentation and Examples&lt;/h4&gt;
&lt;p&gt;Add a &lt;code&gt;README.md&lt;/code&gt; file to your template directory to provide clear instructions on how to use the template, including prerequisites, configuration options, and example commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Go Microservice Golden Path&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;A **golden path** template that gets your Go microservice from code to production on AWS in minutes, not weeks.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;## What You Get&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;This golden path provides everything your development team needs to deploy production-ready Go microservices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Production-ready Go microservice** with Echo framework and OpenTelemetry tracing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **AWS infrastructure that scales** - ECS with auto-scaling from 1-4 instances&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Security by default** - Hardened containers, IAM roles, security groups&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **Monitoring built-in** - Health checks, load balancer monitoring, CloudWatch alarms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **One-command deployment** - `pulumi up` handles everything&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="l"&gt;✅ **No AWS expertise required** - Complex ECS setup abstracted away&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;## For Development Teams: What to Expect&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;### Your Experience&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Getting Started**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Clone this repo, run `pulumi up`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Your service is live on AWS in 5-10 minutes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Public URL provided automatically - no manual setup needed&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Day&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;2-N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Development Workflow**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Write your Go code in `microservice/main.go`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Test locally with `go run main.go`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Deploy changes with `pulumi up`&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;AWS automatically rebuilds and redeploys your container&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;**Production&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Operations**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Service automatically scales with CPU load (80% up, 10% down)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Health checks ensure unhealthy containers are replaced&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Load balancer distributes traffic across healthy instances&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Distributed tracing helps debug issues across services&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;### What&amp;#39;s Handled For You&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;You **don&amp;#39;t** need to learn or configure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;ECS clusters, services, and task definitions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Application Load Balancers and target groups&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Auto-scaling policies and CloudWatch alarms&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Security groups and IAM roles&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Container registries and image building&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Health check configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;You **do** focus on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Writing your Go application logic&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Adding your business endpoints&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Testing your service locally&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- &lt;span class="l"&gt;Deploying with confidence&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="making-templates-available-in-pulumi-idp"&gt;Making Templates Available in Pulumi IDP&lt;/h3&gt;
&lt;p&gt;Publishing your template to &lt;a href="https://www.pulumi.com/docs/idp/"&gt;Pulumi IDP&lt;/a&gt; enables true self-service. Head to &lt;code&gt;Settings&lt;/code&gt; → &lt;code&gt;Integrations&lt;/code&gt; → &lt;code&gt;Organization Template Sources&lt;/code&gt; and add your template repository.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_integrations_view.png" alt="img_4.png"&gt;&lt;/p&gt;
&lt;p&gt;Once published, developers can discover and deploy it directly from the IDP interface.&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_templates_view.png" alt="img_5.png"&gt;&lt;/p&gt;
&lt;p&gt;Now developers can deploy through multiple interfaces:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CLI Deployment:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pulumi new https://github.com/myorg/go-microservice-boilerplate
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;No-Code Deployment:&lt;/strong&gt;
Navigate to &lt;a href="https://www.pulumi.com/docs/idp/get-started/workflows/"&gt;Pulumi IDP&lt;/a&gt; → &lt;code&gt;Templates&lt;/code&gt; → &lt;code&gt;Deploy with Pulumi&lt;/code&gt; → Configure and launch&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_deployment_no_code_view.png" alt="img_7.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Deployment:&lt;/strong&gt;
Navigate to &lt;a href="https://www.pulumi.com/docs/idp/get-started/workflows/"&gt;Pulumi IDP&lt;/a&gt; → &lt;code&gt;Templates&lt;/code&gt; → &lt;code&gt;Deploy with Pulumi&lt;/code&gt; → Configure and launch&lt;/p&gt;
&lt;p&gt;&lt;img src="pulumi_idp_deployment_git_view.png" alt="img_6.png"&gt;&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build golden paths with Pulumi&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Package your infrastructure patterns into reusable components and templates, publish them to a private registry, and let teams deploy production-ready stacks in minutes.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="best-practices-for-reusable-infrastructure-components-and-templates"&gt;Best Practices for Reusable Infrastructure Components and Templates&lt;/h2&gt;
&lt;p&gt;Well-designed components and templates are the foundation of scalable, self-service infrastructure. These best practices ensure your abstractions are maintainable, discoverable, and production-ready.&lt;/p&gt;
&lt;h3 id="1-design-for-day-2-operations-from-day-1"&gt;1. Design for Day 2 Operations from Day 1&lt;/h3&gt;
&lt;p&gt;Think beyond deployment. A golden path must also support ongoing operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How will teams safely update their infrastructure?&lt;/li&gt;
&lt;li&gt;What happens during scaling events?&lt;/li&gt;
&lt;li&gt;How do you handle disaster recovery?&lt;/li&gt;
&lt;li&gt;What metrics and logs are needed for troubleshooting?&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2-expose-complexity-progressively"&gt;2. Expose Complexity Progressively&lt;/h3&gt;
&lt;p&gt;Provide sensible defaults that work, while enabling customization for advanced use cases:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ComponentArgs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Required - what users must provide
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appName&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Common customizations with good defaults
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType?&lt;/span&gt;: &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default: &amp;#34;t3.micro&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;replicas?&lt;/span&gt;: &lt;span class="kt"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// default: 2
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// Advanced options for power users
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;networkConfig?&lt;/span&gt;: &lt;span class="kt"&gt;NetworkConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;securityPolicies?&lt;/span&gt;: &lt;span class="kt"&gt;SecurityPolicy&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;customMetrics?&lt;/span&gt;: &lt;span class="kt"&gt;MetricDefinition&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="4-use-semantic-versioning-everywhere"&gt;4. Use Semantic Versioning Everywhere&lt;/h3&gt;
&lt;p&gt;Clear versioning for both components and templates indicate stability and reliability:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Major versions&lt;/strong&gt; (1.0.0 → 2.0.0): Breaking changes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Minor versions&lt;/strong&gt; (1.0.0 → 1.1.0): New features, backward compatible&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Patch versions&lt;/strong&gt; (1.0.0 → 1.0.1): Bug fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This lets teams adopt updates with confidence and control.&lt;/p&gt;
&lt;h3 id="5-test-your-abstractions"&gt;5. Test Your Abstractions&lt;/h3&gt;
&lt;p&gt;Don&amp;rsquo;t ship black boxes. Create automated tests to validate key functionality and resource creation. Focus on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Smoke tests that validate resource existence&lt;/li&gt;
&lt;li&gt;Output validation to ensure correctness&lt;/li&gt;
&lt;li&gt;Integration tests to confirm end-to-end behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;chai&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kr"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt; &lt;span class="kr"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@pulumi/pulumi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;MicroserviceComponent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;should create required resources&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MicroserviceComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;test&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;appPath&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;./test-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;port&lt;/span&gt;: &lt;span class="kt"&gt;3000&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;pulumi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;allResources&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:ecs/cluster:Cluster&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:ecs/service:Service&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;aws:lb/loadBalancer:LoadBalancer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="how-to-measure-golden-path-success"&gt;How to Measure Golden Path Success&lt;/h2&gt;
&lt;p&gt;Golden paths aren’t complete until they deliver measurable value. Use these KPIs to assess performance and drive iteration:&lt;/p&gt;
&lt;h3 id="adoption-metrics"&gt;Adoption Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Template usage rate&lt;/strong&gt;: Percentage of new projects using golden paths&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Component reuse&lt;/strong&gt;: Number of stacks consuming shared components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time to first deployment&lt;/strong&gt;: Deployment time and frequency from code to production&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="quality-metrics"&gt;Quality Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Security compliance rate&lt;/strong&gt;: Percentage of deployments passing security policies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stability&lt;/strong&gt;: Deployment incident frequency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mean time to recovery (MTTR)&lt;/strong&gt;: Time to recover from production issues&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="developer-experience-metrics"&gt;Developer Experience Metrics&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer satisfaction&lt;/strong&gt;: Survey teams about their platform experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support ticket volume&lt;/strong&gt;: Ticket volume related to infrastructure&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contribution&lt;/strong&gt;: Number of PRs or issues submitted to platform templates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="real-world-results-success-stories"&gt;Real-World Results: Success Stories&lt;/h2&gt;
&lt;p&gt;Organizations using golden paths report significant improvements in speed and reliability:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Snowflake&lt;/a&gt;&lt;/strong&gt; reduced deployment time from 1.5 weeks to less than a day&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/mercedes-benz/"&gt;Mercedes-Benz&lt;/a&gt;&lt;/strong&gt; decreased infrastructure provisioning from weeks to minutes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/case-studies/starburst/"&gt;Starburst Data&lt;/a&gt;&lt;/strong&gt; cut deployment time from 2 weeks to 3 hours&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These results show that golden paths are not just developer tools, they&amp;rsquo;re a competitive advantage. To learn more, download the whitepaper: &lt;a href="https://info.pulumi.com/whitepaper-the-golden-path-to-cloud-success"&gt;The Golden Path to Cloud Success: Your IDP Roadmap&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="common-pitfalls-and-how-to-avoid-them"&gt;Common Pitfalls and How to Avoid Them&lt;/h2&gt;
&lt;h3 id="pitfall-1-over-abstraction"&gt;Pitfall 1: Over-Abstraction&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Creating components so abstract they&amp;rsquo;re unusable
&lt;strong&gt;Solution&lt;/strong&gt;: Start with concrete use cases, then generalize based on actual patterns&lt;/p&gt;
&lt;h3 id="pitfall-2-insufficient-escape-hatches"&gt;Pitfall 2: Insufficient Escape Hatches&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Golden paths become golden cages
&lt;strong&gt;Solution&lt;/strong&gt;: Always provide ways to extend or override default behavior&lt;/p&gt;
&lt;h3 id="pitfall-3-poor-versioning-strategy"&gt;Pitfall 3: Poor Versioning Strategy&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Breaking changes without migration paths
&lt;strong&gt;Solution&lt;/strong&gt;: Maintain backward compatibility and provide clear upgrade guides&lt;/p&gt;
&lt;h3 id="pitfall-4-lack-of-ownership"&gt;Pitfall 4: Lack of Ownership&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Templates become orphaned and outdated
&lt;strong&gt;Solution&lt;/strong&gt;: Assign clear ownership and establish maintenance schedules&lt;/p&gt;
&lt;h2 id="the-future-of-golden-paths-ai-and-beyond"&gt;The Future of Golden Paths: AI and Beyond&lt;/h2&gt;
&lt;p&gt;The future of golden paths is intelligent, cross-cloud, and fully integrated with modern workflows.&lt;/p&gt;
&lt;h3 id="ai-enhanced-templates"&gt;AI-Enhanced Templates&lt;/h3&gt;
&lt;p&gt;Imagine templates that adapt based on your application&amp;rsquo;s actual behavior, automatically tuning resources and configurations for optimal performance and cost.&lt;/p&gt;
&lt;h3 id="cross-cloud-portability"&gt;Cross-Cloud Portability&lt;/h3&gt;
&lt;p&gt;Components that abstract not just resources but entire cloud providers, enabling true multi-cloud golden paths.&lt;/p&gt;
&lt;h3 id="gitops-native-workflows"&gt;GitOps-Native Workflows&lt;/h3&gt;
&lt;p&gt;Templates that include not just infrastructure but complete GitOps pipelines, from code commit to production deployment.&lt;/p&gt;
&lt;h2 id="your-first-steps-to-golden-paths"&gt;Your First Steps to Golden Paths&lt;/h2&gt;
&lt;p&gt;Ready to get started? Here&amp;rsquo;s your action plan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Audit Current Patterns&lt;/strong&gt;: Document the infrastructure patterns your teams use most frequently&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build one reusable component&lt;/strong&gt;: Pick your most common pattern and build a reusable component&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Create Your First Template&lt;/strong&gt;: Build a complete golden path for one project type&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gather Feedback&lt;/strong&gt;: Deploy with a pilot team and iterate based on their experience&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale Gradually&lt;/strong&gt;: Expand your component library and template catalog based on demand&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Measure and Iterate&lt;/strong&gt;: Track adoption and continuously improve based on metrics&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="conclusion-from-fragmentation-to-flow"&gt;Conclusion: From Fragmentation to Flow&lt;/h2&gt;
&lt;p&gt;Golden paths aren&amp;rsquo;t about restricting creativity or enforcing rigid standards. They&amp;rsquo;re about &lt;strong&gt;removing friction&lt;/strong&gt; from the development process, &lt;strong&gt;encoding expertise&lt;/strong&gt; into reusable patterns, and &lt;strong&gt;empowering developers&lt;/strong&gt; to move at the speed of business.&lt;/p&gt;
&lt;p&gt;By building a library of components and templates, you transform your Internal Developer Platform from a collection of tools into a &lt;strong&gt;force multiplier&lt;/strong&gt; for your entire engineering organization. You give developers the gift of not having to solve solved problems, while maintaining the flexibility to innovate where it matters.&lt;/p&gt;
&lt;p&gt;Start small. Solve one problem well. Expand from there. With the right foundation, your developer platform will evolve into a system of self-service, speed, and stability.&lt;/p&gt;
&lt;h3 id="ready-to-build-your-golden-paths"&gt;Ready to Build Your Golden Paths?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code examples&lt;/strong&gt;: &lt;a href="https://github.com/pulumi/workshops/tree/main/golden-paths-infrastructure-components-and-templates"&gt;Explore golden path examples on GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build with Components&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enable Self-Service&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/idp/"&gt;Pulumi IDP documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Join the Community&lt;/strong&gt;: Connect with platform engineers in our &lt;a href="https://slack.pulumi.com"&gt;Pulumi Slack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Next in our series: Policy as Code for Safer IDPs. You will learn how to add automated guardrails that make sure every deployment meets your security and compliance standards without slowing down development.&lt;/em&gt;&lt;/p&gt;</description><author>Engin Diri</author><author>Robert Smith</author><category>internal-developer-platform</category><category>platform-engineering</category><category>golden-paths</category><category>infrastructure-components</category><category>pulumi-templates</category><category>developer-experience</category><category>reusable-infrastructure</category></item><item><title>How to Build an Internal Developer Platform: Strategy, Best Practices, and Self-Service Infrastructure</title><link>https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/</link><pubDate>Thu, 14 Aug 2025 05:13:02 +0200</pubDate><guid>https://www.pulumi.com/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/idp-strategy-planning-self-service-infrastructure-that-balances-developer-autonomy-with-operational-control/index.png" /&gt;
&lt;p&gt;Welcome to the first post in our &lt;strong&gt;IDP Best Practices&lt;/strong&gt; series. In this guide, we’ll walk through the strategic foundations for designing an Internal Developer Platform that empowers developers without sacrificing governance, security, or operational control.&lt;/p&gt;
&lt;p&gt;At Pulumi, we’ve worked with hundreds of teams facing the same core challenge: &lt;strong&gt;How do you give developers the infrastructure access they need, while maintaining the governance and security your organization requires?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That tension is at the heart of every IDP conversation. Teams want to &lt;strong&gt;move faster and innovate&lt;/strong&gt;, but also need to stay compliant, control costs, and maintain operational stability.&lt;/p&gt;
&lt;p&gt;The good news? You can do both, with a clear strategy and the right approach. This series shares &lt;strong&gt;proven best practices&lt;/strong&gt; for designing, building, and scaling IDPs using Pulumi.&lt;/p&gt;
&lt;p&gt;These lessons come from real-world implementations across industries and company sizes—and are built to grow with you.&lt;/p&gt;
&lt;h2 id="understanding-the-platform-engineering-layers-in-your-internal-developer-platform"&gt;Understanding the Platform Engineering Layers in Your Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;&lt;img src="internal-developer-platform-key-layers.png" alt="internal-developer-platform-key-layers.png"&gt;&lt;/p&gt;
&lt;p&gt;When we work with customers on their platform strategy, we often start by referring to the &amp;ldquo;platform engineering layer cake.&amp;rdquo;
Here is a quick walkthrough of each layer and how Pulumi IDP constructs fit this layer cake approach:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: Infrastructure Layer&lt;/strong&gt; - This is your raw cloud resources: VMs, databases, networks, storage.
These are the fundamental building blocks that exist in AWS, Azure, GCP, and other cloud providers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: Platform Layer&lt;/strong&gt; - This is where &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;Pulumi Components&lt;/a&gt; live.
Components take those raw infrastructure resources and package them into higher-level abstractions that encapsulate best practices, security policies, and organizational standards.
For example, instead of manually configuring 15 different AWS resources to create a secure web application, you create a component that handles all that complexity and exposes just the configuration options that matter to your developers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 3: Developer Experience Layer&lt;/strong&gt; - This is where &lt;a href="https://www.pulumi.com/templates/"&gt;Pulumi Templates&lt;/a&gt; and the &lt;a href="https://www.pulumi.com/docs/idp/get-started/private-registry/"&gt;Private Registry&lt;/a&gt; come into play.
Templates provide ready-to-deploy patterns that developers can customize, while the private registry makes everything discoverable and manageable at scale.&lt;/p&gt;
&lt;p&gt;In our workshop, we focused specifically on those top two layers because that&amp;rsquo;s where the transformation happens. This is where you turn raw infrastructure into something developers can actually use productively without becoming infrastructure experts themselves.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how this maps to what you&amp;rsquo;re actually building:&lt;/p&gt;
&lt;h3 id="infrastructure-layer--raw-cloud-resources"&gt;Infrastructure Layer → Raw Cloud Resources&lt;/h3&gt;
&lt;p&gt;Your foundation is still the same: AWS EC2 instances, Azure Virtual Networks, GCP Cloud Functions.
Pulumi&amp;rsquo;s providers give you access to these resources using real programming languages instead of YAML or proprietary DSLs.&lt;/p&gt;
&lt;h3 id="platform-layer--pulumi-components"&gt;Platform Layer → Pulumi Components&lt;/h3&gt;
&lt;p&gt;This is where you create your reusable building blocks. A component might encapsulate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A complete microservice infrastructure pattern (load balancer, auto-scaling group, database, monitoring)&lt;/li&gt;
&lt;li&gt;A secure data pipeline (storage, processing, access controls, encryption)&lt;/li&gt;
&lt;li&gt;A standardized Kubernetes application deployment (ingress, service, deployment, secrets management)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Components are written once in any supported language (TypeScript, Python, Go, .NET, Java) but can be consumed by teams using any of these languages.
This is crucial. Your platform team might write components in Go, but your application teams can consume them in Python or TypeScript.&lt;/p&gt;
&lt;h3 id="developer-experience-layer--templates--private-registry"&gt;Developer Experience Layer → Templates + Private Registry&lt;/h3&gt;
&lt;p&gt;Templates are complete, deployable projects that use your components. They provide:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Getting started patterns: &amp;ldquo;Deploy a new microservice&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Reference architectures: &amp;ldquo;Deploy a three-tier web application&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Environment patterns: &amp;ldquo;Set up a complete dev/staging/prod pipeline&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Private Registry is your distribution mechanism.
It&amp;rsquo;s where components and templates become discoverable, versioned, and manageable.
Developers don&amp;rsquo;t need to hunt through Git repositories or Slack channels to find the right building blocks. Everything is catalogued, documented, and accessible through familiar package management workflows.&lt;/p&gt;
&lt;h2 id="idp-example-building-a-web-application-platform-step-by-step"&gt;IDP Example: Building a Web Application Platform Step-by-Step&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s make this concrete with an example from our workshops.
Say you want to enable teams to deploy secure web applications:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Infrastructure Layer:&lt;/strong&gt; You need an Application Load Balancer, EC2 Auto Scaling Group, RDS database, VPC with proper subnets, Security Groups, IAM roles, CloudWatch monitoring, and S3 bucket for static assets.
That&amp;rsquo;s about 20+ individual AWS resources that need to be configured correctly and securely.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Platform Layer (Components):&lt;/strong&gt; You create a &lt;code&gt;WebApplication&lt;/code&gt; component that encapsulates all this complexity.
Your component exposes simple configuration options like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-typescript" data-lang="typescript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;my-app&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;instanceType&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;t3.medium&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;minSize&lt;/span&gt;: &lt;span class="kt"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;maxSize&lt;/span&gt;: &lt;span class="kt"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;databaseSize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;small&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;production&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Behind the scenes, your component handles all the security configurations, networking setup, monitoring, and best practices.
You publish this component to your private registry.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Developer Experience Layer (Templates):&lt;/strong&gt; You create templates like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;web-app-starter&lt;/code&gt;: A simple web application using your &lt;code&gt;WebApplication&lt;/code&gt; component&lt;/li&gt;
&lt;li&gt;&lt;code&gt;microservice-template&lt;/code&gt;: API service with database and monitoring&lt;/li&gt;
&lt;li&gt;&lt;code&gt;full-stack-template&lt;/code&gt;: Frontend, backend, and database in a complete environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Developers can now run &lt;code&gt;pulumi new web-app-starter&lt;/code&gt; and get a production-ready, secure web application in minutes instead of weeks.
The template uses your component, which handles all the underlying infrastructure complexity.&lt;/p&gt;
&lt;p&gt;This layered approach solves the core challenge we see every platform team struggling with: how do you provide developers with the infrastructure they need without creating operational bottlenecks or compromising security standards.&lt;/p&gt;
&lt;h2 id="why-internal-developer-platforms-matter-in-2025-and-beyond"&gt;Why Internal Developer Platforms Matter in 2025 and Beyond&lt;/h2&gt;
&lt;p&gt;While DevOps brought us incredible advances in how we ship and maintain software, we&amp;rsquo;ve watched many organizations struggle with the unintended consequences: tool sprawl, Day 2 operational pain, and developers who are drowning in infrastructure complexity.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why platform teams have emerged.
You exist to solve these challenges by building tools and workflows that enable your internal customers (the developers) to provision infrastructure and deploy software without getting blocked.
But here&amp;rsquo;s the thing I&amp;rsquo;ve learned from working with hundreds of platform teams: success isn&amp;rsquo;t just about the tools you choose.
It&amp;rsquo;s about the strategy behind how you implement them.&lt;/p&gt;
&lt;h2 id="5-core-components-of-a-successful-internal-developer-platform"&gt;5 Core Components of a Successful Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;Through years of working with platform teams and analyzing what separates successful IDPs from those that struggle to gain adoption, we&amp;rsquo;ve identified five essential components that every platform strategy needs.
These aren&amp;rsquo;t theoretical concepts. They&amp;rsquo;re battle-tested patterns that work across organizations of all sizes and industries.&lt;/p&gt;
&lt;h3 id="1-abstractions"&gt;1. Abstractions&lt;/h3&gt;
&lt;p&gt;Let me be clear about something: abstractions aren&amp;rsquo;t about dumbing down infrastructure for developers.
The abstraction is really where you&amp;rsquo;re hiding the complexity of the underlying infrastructure from your end users, but you&amp;rsquo;re doing it intentionally to provide appropriate interfaces for different personas in your organization.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve seen too many platform teams get this wrong by either over-abstracting (creating black boxes that developers can&amp;rsquo;t customize) or under-abstracting (exposing too much complexity).
The sweet spot is creating &lt;a href="https://www.pulumi.com/docs/iac/concepts/resources/components/"&gt;component resources&lt;/a&gt; that encapsulate your infrastructure patterns and best practices into reusable building blocks that can be consumed across different programming languages and deployment scenarios, while still providing escape hatches when needed.&lt;/p&gt;
&lt;h3 id="2-blueprints"&gt;2. Blueprints&lt;/h3&gt;
&lt;p&gt;Blueprints are your templatized, well-architected patterns that developers can use to bootstrap their infrastructure.
But here&amp;rsquo;s what I want you to understand about blueprints: they&amp;rsquo;re not just starting points that you throw over the wall to developers.
They&amp;rsquo;re carefully designed patterns that embody your organizational best practices and architectural decisions.&lt;/p&gt;
&lt;p&gt;When we see successful platform teams, their templates serve as both accelerators and guardrails.
They give developers a fast path to production-ready infrastructure while ensuring that everything they deploy follows your organization&amp;rsquo;s standards.
That&amp;rsquo;s the power of good blueprint design: speed and compliance working together, not against each other.&lt;/p&gt;
&lt;h3 id="3-workflows"&gt;3. Workflows&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s where many platform teams get trapped: they try to build one workflow to rule them all.
But in our experience working with organizations across every industry, you need to support multiple consumption patterns because you have multiple types of users.
You need:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No-code workflows&lt;/strong&gt; for users who want point-and-click deployment (think product managers or junior developers who just need to spin up a database)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Low-code workflows&lt;/strong&gt; using tools like &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/yaml/"&gt;Pulumi YAML&lt;/a&gt; for configuration-driven infrastructure (perfect for developers who understand infrastructure but don&amp;rsquo;t want to write Go or TypeScript)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Full-code workflows&lt;/strong&gt; for developers who need maximum flexibility and want to leverage the full power of general-purpose programming languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key insight? These aren&amp;rsquo;t three different platforms.
They&amp;rsquo;re three different interfaces to the same underlying components and templates.&lt;/p&gt;
&lt;h3 id="4-security-guardrails"&gt;4. Security guardrails&lt;/h3&gt;
&lt;p&gt;This is probably the most important distinction we can share with you: you want to have guardrails, not gates.
Too many platform teams create approval processes and manual checkpoints that completely undermine the self-service promise they&amp;rsquo;re trying to deliver.&lt;/p&gt;
&lt;p&gt;Guardrails are different.
They start with the best practices and security built into the reusable abstractions. But even the most secure solutions need a safety net.
This safety net is policy-as-code that runs automatically, preventing violations before deployment happens.
When we work with customers on implementing &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi CrossGuard&lt;/a&gt;, we&amp;rsquo;re not creating new friction. We&amp;rsquo;re embedding security, compliance, and cost controls directly into the deployment process.
The developer gets immediate feedback, and you get the assurance that nothing goes to production without meeting your standards.&lt;/p&gt;
&lt;h3 id="5-self-service"&gt;5. Self-service&lt;/h3&gt;
&lt;p&gt;Everything we&amp;rsquo;ve talked about so far builds toward this moment: enabling developers to provision and manage infrastructure independently.
But self-service isn&amp;rsquo;t just about providing a UI. It&amp;rsquo;s about carefully orchestrating all the other components to create experiences that are both powerful and intuitive.&lt;/p&gt;
&lt;p&gt;When we walked through the demo in our workshop, what you saw was the culmination of thoughtful platform design.
Developers can discover available services, deploy infrastructure through whatever interface makes sense for them, and manage their resources over time, all without requiring tickets or manual intervention from platform teams.
That&amp;rsquo;s the promise of a well-designed IDP: developer autonomy without operational chaos.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Put your IDP strategy into practice&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Build reusable components, golden paths, and self-service workflows on Pulumi, and give developers autonomy while you keep governance and costs in check.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="how-to-implement-your-idp-strategy"&gt;How to Implement Your IDP Strategy&lt;/h2&gt;
&lt;h3 id="supporting-different-personas-in-your-internal-developer-platform-design"&gt;Supporting Different Personas in Your Internal Developer Platform Design&lt;/h3&gt;
&lt;p&gt;One of the biggest mistakes we see platform teams make: they try to build for their most sophisticated users first.
But here&amp;rsquo;s what I&amp;rsquo;ve learned from working with hundreds of organizations: you need to think about all your personas from day one.&lt;/p&gt;
&lt;p&gt;In most organizations, you&amp;rsquo;re serving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Infrastructure engineers&lt;/strong&gt; who want full control and flexibility (they&amp;rsquo;ll use the full-code workflows)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application developers&lt;/strong&gt; who need infrastructure but prefer higher-level abstractions (perfect for low-code approaches)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Non-technical users&lt;/strong&gt; who want simple, point-and-click deployment (your no-code users)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The breakthrough insight that separates successful platform teams from struggling ones is this: all these personas can be served by the same underlying components and templates, just consumed through different interfaces.
You don&amp;rsquo;t need to build three different platforms—you need to build one platform with three different consumption models.&lt;/p&gt;
&lt;h3 id="why-a-private-registry-is-key-to-idp-adoption"&gt;Why a Private Registry Is Key to IDP Adoption&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s something we always tell platform teams: if you don&amp;rsquo;t solve the discoverability problem, your beautiful components and templates will sit unused in Git repositories where no one can find them.
That&amp;rsquo;s why the private registry isn&amp;rsquo;t just a nice-to-have. It&amp;rsquo;s the foundation that makes everything else work.&lt;/p&gt;
&lt;p&gt;When you establish a private registry as your source of truth for components, templates, providers, and policies, you&amp;rsquo;re solving two critical problems at once.
First, discoverability: developers can actually find and explore what&amp;rsquo;s available.
Second, lifecycle management: you can see where each package is being used, track version drift, and understand the impact of changes before you make them.&lt;/p&gt;
&lt;p&gt;The workflow is beautifully simple: you publish standardized building blocks with a single &lt;code&gt;pulumi publish&lt;/code&gt; command, and developers discover and consume these assets through familiar package management workflows they already know.&lt;/p&gt;
&lt;h3 id="aligning-your-idp-to-organizational-context-and-services"&gt;Aligning Your IDP to Organizational Context and Services&lt;/h3&gt;
&lt;p&gt;One pattern we see in every successful IDP implementation is that the platform reflects how the organization actually works.
Your developers don&amp;rsquo;t think in terms of individual stacks or resources. They think in terms of services, applications, and business functionality.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why we built &lt;a href="https://www.pulumi.com/docs/idp/get-started/services/"&gt;Pulumi Services&lt;/a&gt; - to let teams logically group stacks and ESC environments in ways that make sense to your organization.
Pulumi Services improve organization by helping your team model infrastructure in a way that&amp;rsquo;s familiar - simplifying Day 2 operations by providing additional context like links to relevant dashboards, Slack channels and more.
When something breaks at 2 AM, your on-call engineer needs to understand dependencies, track usage, and manage infrastructure in the context of the business services that are actually impacted.&lt;/p&gt;
&lt;h2 id="how-to-measure-the-success-of-your-internal-developer-platform"&gt;How to Measure the Success of Your Internal Developer Platform&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s something that might surprise you: the most successful platform teams we work with don&amp;rsquo;t measure their success by how many cool features they&amp;rsquo;ve built.
They measure success by the business outcomes they&amp;rsquo;re driving:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced time-to-market&lt;/strong&gt; through faster infrastructure provisioning (because at the end of the day, your platform exists to help the business move faster)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved developer productivity&lt;/strong&gt; by eliminating infrastructure bottlenecks (happy developers ship more features)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced security posture&lt;/strong&gt; through consistent policy enforcement (security that doesn&amp;rsquo;t slow people down is security that actually gets used)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower operational overhead&lt;/strong&gt; through standardization and automation (because your platform team&amp;rsquo;s time is better spent on innovation than toil)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The numbers speak for themselves.
We&amp;rsquo;ve worked with customers like Snowflake who reduced deployment times from one and a half weeks to less than a day.
Starburst Data cut their infrastructure deployments from two weeks to just three hours.
These aren&amp;rsquo;t vanity metrics. They&amp;rsquo;re business transformations.&lt;/p&gt;
&lt;h2 id="idp-strategy-5-key-steps-to-build-a-strong-foundation"&gt;IDP Strategy: 5 Key Steps to Build a Strong Foundation&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re just starting your IDP journey, here&amp;rsquo;s the roadmap we give to every platform team we work with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start with user research:&lt;/strong&gt; Before you write a single line of code, go talk to your developers.
Understand your different personas and their actual needs, not what you think they need. Do your users like to work from the command line? Do they prefer interacting with a UI?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Identify common patterns:&lt;/strong&gt; Look for infrastructure patterns that get repeated across teams.
These are your goldmine—the patterns that, once abstracted and templatized, will provide immediate value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Begin with components:&lt;/strong&gt; Build reusable infrastructure building blocks before you worry about fancy UIs or workflow orchestration.
You need solid foundations before you can build the house.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Implement progressive disclosure:&lt;/strong&gt; Give people simple interfaces for common use cases, but always provide escape hatches for complex scenarios.
The moment your abstraction becomes a prison, developers will route around it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Measure and iterate:&lt;/strong&gt; Track adoption and gather feedback religiously.
Your platform is only as good as its adoption rate, and adoption only happens when you&amp;rsquo;re solving real problems for real people.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="the-future-of-idps-and-platform-engineering"&gt;The Future of IDPs and Platform Engineering&lt;/h2&gt;
&lt;p&gt;Trends come and go, but platform engineering is here to stay.
It&amp;rsquo;s not just another tool or methodology. This is how modern organizations scale infrastructure to match the speed of innovation. The companies that win are the ones that treat their &lt;strong&gt;Internal Developer Platform (IDP)&lt;/strong&gt; as a strategic foundation, not just a tool.&lt;/p&gt;
&lt;p&gt;Your job isn’t just to manage infrastructure and choose the right tools - it&amp;rsquo;s to enable developers to move faster while keeping governance, security, and costs under control. Get that balance right, and your platform becomes a force multiplier across your entire engineering department.&lt;/p&gt;
&lt;p&gt;The fastest way to get there? Focus on these five essential components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Abstractions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blueprints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workflows&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security guardrails&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-service&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Together, they turn your IDP into more than just infrastructure automation, they create a platform that developers trust and your business relies on.&lt;/p&gt;
&lt;h3 id="ready-to-build-a-successful-idp-that-scales"&gt;Ready to Build a Successful IDP that Scales?&lt;/h3&gt;
&lt;p&gt;Pulumi makes it easy to go from static IaC to dynamic, self-service infrastructure with real programming languages and built-in guardrails.&lt;/p&gt;
&lt;p&gt;Explore &lt;a href="https://www.pulumi.com/product/internal-developer-platforms/"&gt;Pulumi IDP&lt;/a&gt; or &lt;a href="https://app.pulumi.com/signup"&gt;sign up for free&lt;/a&gt; to get started today.&lt;/p&gt;</description><author>Mitch Gerdisch</author><author>Engin Diri</author><category>internal-developer-platform</category><category>platform-engineering</category><category>developer-experience</category><category>self-service</category><category>governance</category><category>components</category><category>templates</category></item><item><title>AI-Assisted Infrastructure as Code with Pulumi's Model Context Protocol Server</title><link>https://www.pulumi.com/blog/mcp-server-ai-assistants/</link><pubDate>Tue, 08 Apr 2025 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/mcp-server-ai-assistants/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/mcp-server-ai-assistants/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Infrastructure as Code (IaC) has revolutionized how we manage cloud resources, but navigating complex cloud provider APIs, writing boilerplate code, and iterating through deployment cycles can still be time-consuming. Pulumi offers a fantastic developer experience using familiar programming languages. But what if we could make it even &lt;em&gt;faster&lt;/em&gt; and more intuitive by integrating powerful AI assistants directly into the development loop?&lt;/p&gt;
&lt;p&gt;This is where the &lt;strong&gt;Pulumi Model Context Protocol (MCP) Server integration&lt;/strong&gt; shines. &lt;a href="https://modelcontextprotocol.io"&gt;MCP&lt;/a&gt; is a specification that allows language models (like the AI in your coding assistant) to interact with external tools and data sources in a structured way. By connecting AI-powered code assistants with Pulumi&amp;rsquo;s CLI and registry via MCP, we can bring real-time resource information and infrastructure management directly into the development environment, dramatically reducing friction and accelerating workflows.&lt;/p&gt;
&lt;p&gt;Several AI coding assistants like GitHub Copilot, Anthropic&amp;rsquo;s Claude Code, Windsurf and others are rapidly evolving; this post will use &lt;strong&gt;Cursor&lt;/strong&gt; (an AI-first code editor) to demonstrate a real-world example of this synergy in action.&lt;/p&gt;
&lt;h2 id="setting-up-the-pulumi-mcp-integration-in-cursor"&gt;Setting up the Pulumi MCP Integration in Cursor&lt;/h2&gt;
&lt;p&gt;Before diving in, you typically need to configure your AI assistant to communicate with the Pulumi MCP server. For Cursor, you can do so by clicking the following button:&lt;/p&gt;
&lt;p&gt;&lt;a href="cursor://anysphere.cursor-deeplink/mcp/install?name=pulumi&amp;amp;config=eyJ0cmFuc3BvcnQiOiJodHRwIiwidXJsIjoiaHR0cHM6Ly9tY3AuYWkucHVsdW1pLmNvbS9tY3AifQ%3D%3D"&gt;&lt;img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Install MCP Server"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The assistant can now leverage Pulumi tools seamlessly. These tools are specific actions enabled by the MCP server—like searching the Pulumi Registry or running a &lt;code&gt;pulumi&lt;/code&gt; command—allowing the assistant to gather information or interact with your Pulumi project.&lt;/p&gt;
&lt;p&gt;For detailed setup instructions for Cursor, Claude Code, Windsurf, Claude Desktop, and other AI assistants, see the &lt;a href="https://www.pulumi.com/docs/iac/using-pulumi/mcp-server/"&gt;Pulumi MCP Server documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-goal-provisioning-an-aks-cluster"&gt;The Goal: Provisioning an AKS Cluster&lt;/h2&gt;
&lt;p&gt;Our objective for this walkthrough is to provision a temporary Azure Kubernetes Service (AKS) cluster for a short experiment using Pulumi and TypeScript. We need the cluster created with minimal fuss and its &lt;code&gt;kubeconfig&lt;/code&gt; exported for access.&lt;/p&gt;
&lt;h2 id="the-traditional-approach"&gt;The Traditional Approach&lt;/h2&gt;
&lt;p&gt;The conventional method for this task involves significant context switching: searching Azure and Pulumi documentation in a browser, writing code in an editor, running commands (&lt;code&gt;pulumi preview&lt;/code&gt;, &lt;code&gt;pulumi up&lt;/code&gt;) in a terminal, and manually correlating information between these different environments. This process can be slow, requires deep knowledge recall (or constant lookups), and is prone to errors during the manual translation from documentation to code.&lt;/p&gt;
&lt;h2 id="the-ai-assistant--pulumi-mcp-approach"&gt;The AI Assistant + Pulumi MCP Approach&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s walk through how the same task unfolds much more efficiently using an AI assistant integrated with Pulumi MCP.&lt;/p&gt;
&lt;h3 id="understanding-the-ai-assistant--tool-interaction"&gt;Understanding the AI Assistant + Tool Interaction&lt;/h3&gt;
&lt;p&gt;Before detailing the steps, it&amp;rsquo;s helpful to understand the user interface flow when the AI assistant uses integrated tools like those provided by the Pulumi MCP integration. Typically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The developer provides a prompt or instruction in the chat interface within their editor.&lt;/li&gt;
&lt;li&gt;The AI assistant analyzes the request and determines that it needs specific information (like resource properties) or needs to perform an action (like running &lt;code&gt;pulumi preview&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;The assistant indicates it will use a specific tool (e.g., &lt;code&gt;pulumi_registry_listResources&lt;/code&gt;, &lt;code&gt;pulumi_cli_preview&lt;/code&gt;). This often appears as a distinct UI element in the chat, showing the tool name and parameters being used.&lt;/li&gt;
&lt;li&gt;The tool executes via the MCP server, interacting with the Pulumi CLI or registry as needed.&lt;/li&gt;
&lt;li&gt;The output or result from the tool (e.g., registry listings, preview results, deployment errors) is displayed directly in the chat interface.&lt;/li&gt;
&lt;li&gt;The AI assistant processes this output and uses it to continue the task – either by generating code, providing an answer, or deciding on the next step (like suggesting a fix for an error).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This tight loop keeps the developer focused within their editor environment, minimizing disruptions.&lt;/p&gt;
&lt;p&gt;&lt;img src="cursor-tool-calls.png" alt="Cursor calling Pulumi tools"&gt;&lt;/p&gt;
&lt;h3 id="step-by-step-walkthrough"&gt;Step-by-Step Walkthrough&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s how the AKS provisioning task played out:&lt;/p&gt;
&lt;h4 id="the-request"&gt;The Request&lt;/h4&gt;
&lt;p&gt;The developer starts with a natural language request to the AI assistant within the editor:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I have an empty Pulumi project with TypeScript. Please edit the program to provision an AKS cluster for me. It&amp;rsquo;s a temporary AKS cluster that I need for a short experiment, so I don&amp;rsquo;t need any particular configuration of it. Just export its kubeconfig when you are done. Please use the tools to lookup resource information and to run pulumi preview to make sure your code works. When done, run pulumi up for me.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="ai-powered-resource-discovery"&gt;AI-Powered Resource Discovery&lt;/h4&gt;
&lt;p&gt;Instead of the developer manually searching docs, the AI assistant leverages the MCP integration.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The AI assistant first queries the Pulumi Registry via MCP to list resources within the Azure Native provider&amp;rsquo;s &lt;code&gt;containerservice&lt;/code&gt; module (using the &lt;code&gt;pulumi_registry_listResources&lt;/code&gt; tool). This immediately identified &lt;code&gt;ManagedCluster&lt;/code&gt; as the relevant resource.&lt;/li&gt;
&lt;li&gt;The AI assistant then requests detailed information &lt;em&gt;specifically&lt;/em&gt; for &lt;code&gt;ManagedCluster&lt;/code&gt; (using &lt;code&gt;pulumi_registry_getResource&lt;/code&gt;), directly retrieving its required properties, descriptions, and structure without leaving the editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="registry-tools.png" alt="Cursor calling Pulumi tools"&gt;&lt;/p&gt;
&lt;h4 id="ai-code-generation--editing"&gt;AI Code Generation &amp;amp; Editing&lt;/h4&gt;
&lt;p&gt;Using the information retrieved from the Pulumi Registry, the assistant generated the necessary TypeScript code. It defined the &lt;code&gt;ManagedCluster&lt;/code&gt; resource with a basic configuration and used its code editing capabilities to insert the code directly into the developer&amp;rsquo;s &lt;code&gt;index.ts&lt;/code&gt; file.&lt;/p&gt;
&lt;h4 id="integrated-validation"&gt;Integrated Validation&lt;/h4&gt;
&lt;p&gt;Before attempting a potentially time-consuming deployment, the assistant ran &lt;code&gt;pulumi preview&lt;/code&gt; using the integrated CLI tool (&lt;code&gt;pulumi_cli_preview&lt;/code&gt;). The preview output appeared directly in the chat.&lt;/p&gt;
&lt;p&gt;The preview succeeded, showing the resources that would be created. The assistant then proceeded to run &lt;code&gt;pulumi up&lt;/code&gt; using the integrated CLI tool (&lt;code&gt;pulumi_cli_up&lt;/code&gt;). However, the deployment flagged an error: an incorrect attempt to interpolate a Pulumi &lt;code&gt;Output&amp;lt;string&amp;gt;&lt;/code&gt; directly into a resource property.&lt;/p&gt;
&lt;p&gt;&lt;img src="up-failed.png" alt="Pulumi UP tool failed due to incorrect interpolation"&gt;&lt;/p&gt;
&lt;h4 id="ai-assisted-debugging--iteration"&gt;AI-Assisted Debugging &amp;amp; Iteration&lt;/h4&gt;
&lt;p&gt;The assistant analyzed the error message from the tool:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It identified the incorrect string interpolation and proposed a fix (using &lt;code&gt;pulumi.interpolate&lt;/code&gt;), applying it via the editing tool.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Self-correction:&lt;/em&gt; The first fix inadvertently introduced a circular dependency (caught by linters integrated into the editor and surfaced to the assistant). The assistant recognized this and further refined the code by removing the problematic property, correctly relying on Azure&amp;rsquo;s default behavior.&lt;/li&gt;
&lt;li&gt;Another attempt to deploy using &lt;code&gt;pulumi up&lt;/code&gt; failed, this time surfacing an Azure API error: the provided SSH key format was invalid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="ssh-key.png" alt="Pulumi UP tool failed due to incorrect SSH key"&gt;&lt;/p&gt;
&lt;h4 id="collaborative-problem-solving--tooling"&gt;Collaborative Problem Solving &amp;amp; Tooling&lt;/h4&gt;
&lt;p&gt;The developer, seeing the SSH key error, suggested using the Pulumi TLS package to generate a valid key dynamically.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The assistant used the integrated terminal tool to execute &lt;code&gt;npm install @pulumi/tls&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It then edited the &lt;code&gt;index.ts&lt;/code&gt; file again, incorporating the &lt;code&gt;tls.PrivateKey&lt;/code&gt; resource and correctly using its &lt;code&gt;publicKeyOpenssh&lt;/code&gt; output for the &lt;code&gt;ManagedCluster&lt;/code&gt;&amp;rsquo;s Linux profile.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src="tls-key.png" alt="Use the Pulumi TLS provider"&gt;&lt;/p&gt;
&lt;h4 id="successful-deployment"&gt;Successful Deployment&lt;/h4&gt;
&lt;p&gt;The subsequent &lt;code&gt;pulumi preview&lt;/code&gt; showed the correct plan (including the new TLS key resource). The assistant then executed &lt;code&gt;pulumi up&lt;/code&gt;, which completed successfully. The success message and resource summary appeared in the chat.&lt;/p&gt;
&lt;p&gt;&lt;img src="success.png" alt="Successful Deployment"&gt;&lt;/p&gt;
&lt;h4 id="accessing-outputs"&gt;Accessing Outputs&lt;/h4&gt;
&lt;p&gt;Finally, retrieving the &lt;code&gt;kubeconfig&lt;/code&gt; was trivial. The assistant used the stack output tool (&lt;code&gt;pulumi_cli_stack_output kubeconfig&lt;/code&gt;) to fetch and display the configuration directly.&lt;/p&gt;
&lt;p&gt;&lt;img src="stack-output.png" alt="Stack Output showing Kubeconfig"&gt;&lt;/p&gt;
&lt;h2 id="why-this-changes-the-game"&gt;Why This Changes the Game&lt;/h2&gt;
&lt;p&gt;Integrating AI assistants with the Pulumi Model Context Protocol offers tangible benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Reduced Context Switching:&lt;/strong&gt; The entire workflow – discovery, coding, validation, deployment, debugging, output retrieval – happens primarily &lt;em&gt;inside&lt;/em&gt; the editor. No more juggling browser tabs and terminal windows.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accelerated Discovery:&lt;/strong&gt; MCP integration provides immediate, context-aware access to Pulumi resource schemas and documentation snippets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Faster Coding:&lt;/strong&gt; AI generates boilerplate and resource definitions quickly based on registry data and natural language requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tighter Feedback Loop:&lt;/strong&gt; &lt;code&gt;pulumi preview&lt;/code&gt; and &lt;code&gt;pulumi up&lt;/code&gt; results are instantly available within the coding environment, enabling rapid iteration.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Intelligent Assistance &amp;amp; Collaboration:&lt;/strong&gt; The AI assists with debugging complex errors, incorporates developer suggestions, and leverages integrated tooling effectively.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;The synergy between AI coding assistants and the Pulumi Model Context Protocol (MCP) integration creates a remarkably efficient environment for Infrastructure as Code development. By bringing cloud resource knowledge, code generation, and the Pulumi CLI workflow directly into the editor, developers can build, deploy, and iterate on their infrastructure faster and with significantly less friction.&lt;/p&gt;
&lt;p&gt;Whether you use Cursor, Copilot, Claude Code, Windsurf, or another emerging AI tool, integrating it with the Pulumi MCP server offers a glimpse into the future of streamlined, intelligent IaC development, ultimately boosting productivity and improving the overall developer experience.&lt;/p&gt;</description><author>Mikhail Shilkov</author><category>features</category><category>infrastructure-as-code</category><category>ai</category><category>developer-experience</category></item><item><title>Your Perfect Infrastructure May Not Be So Perfect</title><link>https://www.pulumi.com/blog/your-perfect-infrastructure/</link><pubDate>Mon, 16 Dec 2024 10:43:07 +0000</pubDate><guid>https://www.pulumi.com/blog/your-perfect-infrastructure/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/your-perfect-infrastructure/index.png" /&gt;
&lt;p&gt;&lt;strong&gt;Guest Article:&lt;/strong&gt; &lt;em&gt;Simen A. W. Olsen from &lt;a href="https://bjerk.io"&gt;Bjerk&lt;/a&gt;, is here to share his lessons learned on why designing the perfect architecture for your future needs might be a mistake&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I remember standing in front of our engineering team in 2018, proudly presenting what I believed was the future-proof architectural design for our new distributed system. The diagrams were immaculate, the technology choices were cutting-edge, and the scalability patterns were ready for any possible future scenario.&lt;/p&gt;
&lt;p&gt;I was basically the Leonardo da Vinci of system design… if Leonardo had been really into Kubernetes and had a concerning addiction to coffee. But six months later, that “future-proof” architecture had become a constraint rather than an enabler, and my masterpiece was looking more like a finger painting done by a caffeinated raccoon.&lt;/p&gt;
&lt;p&gt;This experience taught me something crucial: trying to build the perfect system that anticipates every future need is often worse than creating a system designed to change quickly. It’s like trying to predict what your kid will want to be when they grow up and pre-buying all the necessary equipment. Congrats, you now own a space suit, a stethoscope, and a dragon costume — and they decided to become a software engineer anyway.&lt;/p&gt;
&lt;h2 id="the-over-planning"&gt;The Over-Planning&lt;/h2&gt;
&lt;p&gt;Many teams fall into a common trap: they try to design systems that anticipate every possible future requirement. This happens even in agile teams, where we convince ourselves we need to “get the architecture right” before we can start iterating. You know, because nothing says “agile” like spending three months in a room drawing boxes and arrows while muttering “microservices” under your breath like it’s a magic spell.&lt;/p&gt;
&lt;p&gt;In 2008, Netflix faced a choice: build the perfect data center that could handle all their anticipated future needs, or move to the cloud with a simpler architecture that could evolve. They chose the latter, focusing on making their system easy to change rather than trying to make it perfect. Smart move — unlike those my past self made who probably would’ve insisted on building a data center capable of streaming to Mars, just in case Elon asked nicely.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;
&lt;p&gt;&lt;strong&gt;You might also like:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/p3-some-assembly-required/"&gt;
Pulumi Patterns and Practices Platform (P3): Some Assembly Required
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;
Pulumi Patterns and Practices Platform (P3): A reference architecture for large-scale organizations
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/next-level-iac-briding-the-declarative-gap/"&gt;
Next-level IaC: Bridging the Declarative Gap
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-core-principles-of-change-ready-architecture"&gt;The Core Principles of Change-Ready Architecture&lt;/h2&gt;
&lt;p&gt;Through both failures and successes, I’ve identified three principles that define truly adaptable architecture:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Embrace simplicity.&lt;/strong&gt; I think it makes sense to start with the simplest architecture that could possibly work for your current needs. Complexity should be earned, not presumed. If your architecture diagram looks like a plate of spaghetti that’s been hit by lightning, you might be doing it wrong.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make change cheap.&lt;/strong&gt; Instead of trying to avoid change, make it inexpensive. This means investing in automated testing, continuous deployment, and monitoring. When change is cheap, you don’t need to fear it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Learn through action.&lt;/strong&gt; Rather than trying to predict the future, build mechanisms that help you learn quickly about real needs. It includes feature toggles (Protip: Try &lt;a href="https://www.getunleash.io/"&gt;Unleash&lt;/a&gt;.), A/B testing, and robust monitoring of how your system is actually being used. You know, actual data, not just what that one loud guy in planning insists will definitely happen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The rise of AI and machine learning systems has made one thing clear: we can’t predict how our systems will need to evolve. The most successful teams aren’t those that try to build the perfect AI architecture upfront, but those that can rapidly experiment and adapt their systems based on real-world feedback.&lt;/p&gt;
&lt;p&gt;The biggest pushback I hear is, “But what if we need to scale?” or “What about future requirements?” These fears often drive teams to over-architect their solutions. But here’s the reality: the cost of changing a simple system is usually lower than the cost of maintaining an over-engineered one. The key is understanding that good architecture isn’t about predicting the future — it’s about making future changes as painless as possible.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;That over-engineered system I was so proud of in 2018? Its most significant flaw wasn’t in what it got wrong about the future — it was that it tried too hard to be right about the future in the first place. It’s like bringing a fully packed suitcase to a first date. Today, I know that the best architecture isn’t one that anticipates every need, but one that makes it easy to respond to needs as they emerge.&lt;/p&gt;
&lt;p&gt;The next time you’re tempted to design for every possible future scenario, remember: the goal isn’t to build a perfect system, but to build one that’s perfectly easy to change. And if someone tells you they’ve designed the perfect future-proof architecture, they’re either lying, or they’ve discovered time travel — and in that case, they should be sharing lottery numbers, not system designs.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;
&lt;p&gt;&lt;strong&gt;You might also like:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/p3-some-assembly-required/"&gt;
Pulumi Patterns and Practices Platform (P3): Some Assembly Required
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;
Pulumi Patterns and Practices Platform (P3): A reference architecture for large-scale organizations
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.pulumi.com/blog/next-level-iac-briding-the-declarative-gap/"&gt;
Next-level IaC: Bridging the Declarative Gap
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description><author>Simen A. W. Olsen</author><category>architecture</category><category>developer-first-infrastructure</category><category>best-practices</category><category>cloud-engineering</category><category>cloud-deployment</category><category>developer-experience</category><category>people-ops</category><category>application-scalability</category></item><item><title>Integrating DevOps and Security in Platform Engineering</title><link>https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/</link><pubDate>Wed, 11 Dec 2024 07:41:06 +0000</pubDate><guid>https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/integrating-devops-and-security-for-scalable-platform-engineering/index.png" /&gt;
&lt;p&gt;Platform engineering has become essential for mid-to-large organizations, moving beyond a DevOps trend. Gartner predicts that by 2026, 80% of software companies will have internal platform services to streamline development. The goal is to empower developers with self-service tools while maintaining security, compliance, and reliability through DevSecOps practices.&lt;/p&gt;
&lt;p&gt;At PulumiUP Europe 2024, experts shared insights on aligning DevOps with security to build scalable, secure platforms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Jess Mink, Sr. Director of Platform Engineering at Honeycomb&lt;/li&gt;
&lt;li&gt;Kief Morris, Global Head of Infrastructure Engineering at ThoughtWorks&lt;/li&gt;
&lt;li&gt;Lindsay Jack, VP of Engineering &amp;amp; Security at Snyk&lt;/li&gt;
&lt;li&gt;Nariman Aga-Tagiyev, Application Security Architect at WiseFrog Security&lt;/li&gt;
&lt;li&gt;Komal Ali, Engineering Manager at Pulumi&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The panel discussed key strategies, challenges, and pillars of successful platform engineering.&lt;/p&gt;
&lt;h2 id="in-this-article"&gt;In this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#the-core-pillars-of-platform-engineering"&gt;The Core Pillars of Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#aligning-devops-and-security-for-secure-platform-engineering"&gt;Aligning DevOps and Security for Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#shift-left-security"&gt;Shift Left Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#embrace-automation-and-standardization"&gt;Embrace Automation and Standardization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#prioritize-observability-and-monitoring"&gt;Prioritize Observability and Monitoring&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#foster-a-culture-of-collaboration"&gt;Foster a Culture of Collaboration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#challenges-of-integrating-security-in-platform-engineering"&gt;Challenges of Integrating Security in Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#balancing-autonomy-and-control"&gt;Balancing Autonomy and Control&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#driving-adoption-and-changing-mindsets"&gt;Driving Adoption and Changing Mindsets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#adapting-to-evolving-needs-and-technologies"&gt;Adapting to Evolving Needs and Technologies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#measuring-success-in-secure-platform-engineering"&gt;Measuring Success in Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/integrating-devops-and-security-for-scalable-platform-engineering/#the-future-of-secure-platform-engineering"&gt;The Future of Secure Platform Engineering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-core-pillars-of-platform-engineering"&gt;The Core Pillars of Platform Engineering&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/WUpyqn1Jfwg?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/"&gt;Platform engineering teams&lt;/a&gt; comprise multiple professionals with many responsibilities and focus areas. According to our panel of experts, the core pillars of platform engineering include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;Developer Experience (DevEx)&lt;/a&gt;&lt;/strong&gt;: Provide developers with the tools, frameworks, and abstractions they need to be productive and proactive without getting stuck in infrastructure or operational concerns.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#an-effective-internal-developer-platform"&gt;Reliability and Scalability&lt;/a&gt;&lt;/strong&gt;: Ensure that the platform and infrastructure can support the organization&amp;rsquo;s needs, with the ability to scale up or down as required.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;Security and Compliance&lt;/a&gt;&lt;/strong&gt;: Embed robust, accessible security and compliance frameworks into the development lifecycle while making it easy for developers to adhere to these policies.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/automation-api/"&gt;Automation and Tooling&lt;/a&gt;&lt;/strong&gt;: Leverage &lt;a href="https://www.pulumi.com/product/infrastructure-as-code/"&gt;Infrastructure as Code (IaC)&lt;/a&gt; and automation to enforce standardized processes and consistency and reduce cognitive load and manual effort.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Observability and Monitoring&lt;/a&gt;&lt;/strong&gt;: Provide visibility into the platform&amp;rsquo;s health and performance, delivering actionable insights that allow teams to identify and resolve issues quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These pillars work together to create a platform that empowers developers to innovate and deliver value to the organization and customers while maintaining the necessary controls and safeguards.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Jess Mink, Director of Platform Engineering at &lt;a href="https://www.pulumi.com/blog/observability-with-infrastructure-as-code/"&gt;Honeycomb&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;The goal of platform engineering is to help the company run smoother and faster and unlock things people didn&amp;rsquo;t know were possible [&amp;hellip;] We tend to focus on tools and software, but it&amp;rsquo;s really about people, processes, and tools. If you consider this, platforms are responsible for social and technical support across the organization. A common pitfall is building tools no one uses because you didn’t meet people where they are.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="aligning-devops-and-security-for-secure-platform-engineering"&gt;Aligning DevOps and Security for Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Integrating security into platform engineering ensures it becomes a proactive part of the development lifecycle and ensures that &amp;ldquo;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/"&gt;DevSecOps&lt;/a&gt;&amp;rdquo; is not an afterthought but a core consideration.&lt;/p&gt;
&lt;p&gt;Key best practices shared by the panel include:&lt;/p&gt;
&lt;h3 id="shift-left-security"&gt;Shift Left Security&lt;/h3&gt;
&lt;p&gt;One of the fundamental principles of DevSecOps is to &amp;ldquo;shift left&amp;rdquo; - that is, to integrate security earlier in the development process rather than waiting until the end. This can involve activities such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Incorporating security requirements and threat modeling into the initial design phase&lt;/li&gt;
&lt;li&gt;Automating security scans and tests as part of the continuous integration (CI) pipeline&lt;/li&gt;
&lt;li&gt;Providing developers with secure coding guidelines and tools to &lt;a href="https://www.pulumi.com/blog/drift-detection/#why-pulumi-cloud-drift-detection-and-remediation"&gt;identify and remediate vulnerabilities&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By addressing security concerns upfront, organizations can reduce the time and cost of remediating issues later in the development lifecycle.&lt;/p&gt;
&lt;h3 id="embrace-automation-and-standardization"&gt;Embrace Automation and Standardization&lt;/h3&gt;
&lt;p&gt;Consistency is key. Platform engineering teams should leverage automation and built-in safeguards and security processes. This may include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automating the provisioning of secure infrastructure and application environments&lt;/li&gt;
&lt;li&gt;Implementing Infrastructure as Code (IaC) to define and &lt;a href="https://www.pulumi.com/blog/pulumi-is-imperative-declarative-imperative/"&gt;manage infrastructure in a declarative&lt;/a&gt;, version-controlled manner&lt;/li&gt;
&lt;li&gt;Standardizing security controls, policies, and configurations across the platform&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By automating these tasks, platform engineering teams can reduce the risk of human error, improve visibility and auditability, and free up developers to focus on building features rather than managing infrastructure.&lt;/p&gt;
&lt;h3 id="prioritize-observability-and-monitoring"&gt;Prioritize Observability and Monitoring&lt;/h3&gt;
&lt;p&gt;Effective security requires visibility into the health and performance of the platform. Platform engineering teams should invest in robust observability and monitoring solutions to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/drift-detection/"&gt;Detect and respond&lt;/a&gt; to security incidents and anomalies in real-time&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Gain insights&lt;/a&gt; into the behavior and usage patterns of the platform&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#policy-enforcement-ensuring-compliance-and-security"&gt;Identify and address&lt;/a&gt; vulnerabilities or misconfigurations proactively&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By integrating security-focused monitoring and alerting into the platform, organizations can quickly identify and mitigate threats while also providing developers with the necessary context to understand and address security-related issues.&lt;/p&gt;
&lt;h3 id="foster-a-culture-of-collaboration"&gt;Foster a Culture of Collaboration&lt;/h3&gt;
&lt;p&gt;Platform engineering is often referred to as being the practical application of DevOps practices. Integrating security practices often requires a cultural shift towards collaboration and shared responsibility between all teams in development, operations, and security, thus the name DevSecOps. Platform engineering teams can facilitate this by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Treating &lt;a href="https://www.pulumi.com/blog/platform-engineering-cncf-maturity-model/#platforms-as-products-driving-success"&gt;Platforms as Products&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Involving security stakeholders in the design and planning of platform initiatives&lt;/li&gt;
&lt;li&gt;Providing security training and education to developers to empower them to make informed decisions&lt;/li&gt;
&lt;li&gt;Establishing communication channels and feedback loops between teams&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Kief Morris, Global Head of Infrastructure Engineering at &lt;a href="https://www.thoughtworks.com/en-us"&gt;ThoughtWorks&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;There is a new way of thinking that is trying to avoid that &amp;ldquo;build it, and they will come mentality,&amp;rdquo; which leads to building it and nobody using it. One of the trends we are seeing is product thinking [&amp;hellip;]—using techniques like creating user personas of different types of users in the organization, conducting research to understand their needs, and talking with them.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Breaking silos and fostering communication helps organizations build secure, scalable platforms that support the needs of developers, platform engineers, architects, and security teams.&lt;/p&gt;
&lt;h2 id="challenges-of-integrating-security-in-platform-engineering"&gt;Challenges of Integrating Security in Platform Engineering&lt;/h2&gt;
&lt;p&gt;While the benefits of integrating DevOps and security in platform engineering are clear, the journey has expected challenges. Our panel of experts highlighted several key obstacles that organizations may face:&lt;/p&gt;
&lt;h3 id="balancing-autonomy-and-control"&gt;Balancing Autonomy and Control&lt;/h3&gt;
&lt;p&gt;The primary goal is to empower developers to be more productive and proactive. However, this autonomy needs to be balanced with necessary security controls and governance measures.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Jess Mink points out the importance of achieving harmony between developer autonomy and operational control, stating:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;It&amp;rsquo;s a delicate balance - you want to make things easy for developers, but you also need to maintain the right level of control and security. It&amp;rsquo;s about finding the right abstractions and interfaces that give developers the freedom they need while still ensuring the platform remains secure and compliant.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 id="driving-adoption-and-changing-mindsets"&gt;Driving Adoption and Changing Mindsets&lt;/h3&gt;
&lt;p&gt;Integrating security into the platform engineering workflow can often be met with resistance from developers accustomed to moving quickly and may view security as an obstacle to their productivity.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Nariman, a Software Security Architect, notes:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;The challenge is not just about the tools or the technology - it&amp;rsquo;s about changing the mindset and getting people to understand the importance of security. You need to find ways to motivate developers and make them feel like they&amp;rsquo;re part of the solution rather than just imposing more rules and processes.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Effective communication, education, and a focus on the business value of security are key to driving adoption and fostering a culture of shared responsibility.&lt;/p&gt;
&lt;h3 id="adapting-to-evolving-needs-and-technologies"&gt;Adapting to Evolving Needs and Technologies&lt;/h3&gt;
&lt;p&gt;As organizations grow and their technology stacks evolve, the demands on the platform engineering team can shift rapidly. Keeping up with these changes, while maintaining a secure and reliable platform, can be a significant challenge.&lt;/p&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;Lindsay Jack, VP of Engineering for the Platform Division at &lt;a href="https://partners.snyk.io/English/solutions/solution/2908/pulumi"&gt;Snyk&lt;/a&gt;, explains:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;You might have a platform team that&amp;rsquo;s really good at a certain set of technologies, but then the organization starts moving in a new direction, and suddenly those skills don&amp;rsquo;t match up anymore. It&amp;rsquo;s about being agile and adaptable and making sure you have the right mix of skills and expertise to support the organization&amp;rsquo;s evolving needs&lt;/em&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Fostering internal mobility, continuous learning, and a flexible, modular platform architecture can help platform engineering teams navigate these changes more effectively.&lt;/p&gt;
&lt;h2 id="measuring-success-in-secure-platform-engineering"&gt;Measuring Success in Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Measuring the success of a platform engineering initiative can be complex as it involves balancing a range of technical, operational, and business-oriented metrics but also considers human factors. According to our panel, some key metrics to include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: Metrics such as developer satisfaction surveys, time-to-onboard new developers, and the number of self-service platform capabilities can provide insights into the effectiveness of the platform in supporting developer productivity and autonomy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reliability and Scalability&lt;/strong&gt;: Monitoring service-level objectives (SLOs), incident response times, and the ability to handle increased traffic or user demands can help assess the platform&amp;rsquo;s reliability and scalability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and Compliance&lt;/strong&gt;: Tracking the number of security incidents, the ratio of security issues found during threat modeling versus post-deployment, and the adoption of security best practices can indicate the platform&amp;rsquo;s security posture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automation and Tooling&lt;/strong&gt;: Metrics like the percentage of infrastructure provisioned through code, the frequency of platform updates, and the time saved through automation can demonstrate the platform&amp;rsquo;s operational efficiency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability and Monitoring&lt;/strong&gt;: Measuring the effectiveness of observability tools, the time to detect and resolve issues, and the quality of incident reports can &lt;a href="https://www.pulumi.com/blog/insights-cloud-account-discovery/"&gt;provide insights into the platform&amp;rsquo;s overall health&lt;/a&gt; and performance.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="note note-tip"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-lightbulb-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;&lt;p&gt;As Jess Mink emphasizes, it&amp;rsquo;s important not just to collect these metrics but to use them to drive meaningful action and improvement:&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;em&gt;We look at all of those [metric categories] every quarter and write summaries that go up to the executive level. This creates visibility and a shared understanding of problems so that there&amp;rsquo;s room for movement and change in the right ways.&lt;/em&gt;&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="the-future-of-secure-platform-engineering"&gt;The Future of Secure Platform Engineering&lt;/h2&gt;
&lt;p&gt;Software development and infrastructure management are evolving, and the role of platform engineering will only become more critical to support it. By integrating DevOps and security practices, platform engineering teams can create scalable, secure platforms that empower developers to be more productive and innovate, delivering business value.&lt;/p&gt;
&lt;p&gt;Learn how Pulumi customers build secure, scalable platforms and empower their development teams:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tivity Health&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/"&gt;DevSecOps Game-Changer: Security Automation That Delivers Business Results&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BMW Group&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/"&gt;Unified and Programmatic Approach to Infrastructure Management at BMW Using Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lemonade&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/case-studies/lemonade/"&gt;How the DevOps team supports a much larger group of developers&lt;/a&gt; using by Pulumi to standardize infrastructure components and enforce best practices.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Discover platform engineering best practices in &lt;a href="https://www.pulumi.com/blog/the-guide-platform-engineering-idp-steps-best-practices/"&gt;The Guide to Platform Engineering: 7 Steps to Get It Right&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Build secure, scalable platforms with confidence—get started with the &lt;a href="https://info.pulumi.com/platform-engineering-workshop-series"&gt;Platform Engineering Workshop Series &amp;amp; Course&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</description><author>Sara Huddleston</author><category>devsecops</category><category>platform-engineering</category><category>developer-experience</category><category>devops</category><category>security</category></item><item><title>DevSecOps Game-Changer: Security Automation That Delivers Business Results</title><link>https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/</link><pubDate>Thu, 21 Nov 2024 07:16:30 +0000</pubDate><guid>https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/devsecops-strategy-security-automation-tivity-health/index.png" /&gt;
&lt;p&gt;Organizations are under constant pressure to deliver new products and features faster than ever. But speed alone isn’t enough—businesses must also navigate the complex challenges of ensuring security and managing infrastructure costs effectively.&lt;/p&gt;
&lt;p&gt;Enter DevSecOps - the strategic integration of security practices into the DevOps workflow. By automating security processes, organizations can achieve improved speed, scalability, and business impact, all while ensuring security remains a priority.&lt;/p&gt;
&lt;p&gt;Tivity Health, a leading health and fitness solutions provider, has embraced this DevSecOps approach using Pulumi, a modern infrastructure as code (IaC) platform. During PulumiUP 2024, David Giambruno, Tivity Health&amp;rsquo;s VP of Engineering and DevOps, shared how, by leveraging Pulumi, he led the transformation that continuously drives remarkable results in speed, cost savings, and security.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#the-beginning-from-data-center-to-the-cloud"&gt;The Beginning: From Data Center to the Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#embracing-pulumi-the-power-of-automation-productivity-and-security"&gt;Embracing Pulumi: The Power of Automation, Productivity, and Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#driving-business-impact-through-security-automation"&gt;Driving Business Impact Through Security Automation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#fostering-devops-culture-through-cross-functional-collaboration"&gt;Fostering DevOps Culture Through Cross-Functional Collaboration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#lessons-learned-navigating-the-cultural-shift"&gt;Lessons Learned: Navigating the Cultural Shift&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/devsecops-strategy-security-automation-tivity-health/#the-future-of-devsecops-and-pulumi-at-tivity-health"&gt;The Future of DevSecOps and Pulumi at Tivity Health&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-beginning-from-data-center-to-the-cloud"&gt;The Beginning: From Data Center to the Cloud&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.tivityhealth.com/"&gt;Tivity Health&lt;/a&gt;&amp;rsquo;s journey began with a strategic decision to transition from a traditional data center environment to a cloud-native architecture. Rather than opting for a &amp;ldquo;lift and shift&amp;rdquo; approach, they made the bold choice to go directly to a cloud-native model, embracing the principles of DevSecOps along the way.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/35vAiKdDux4?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;The need to &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;automate infrastructure deployment&lt;/a&gt; and management was fundamental. Giambruno explained, &amp;ldquo;&lt;em&gt;If you can&amp;rsquo;t automate it, we don&amp;rsquo;t need it.&lt;/em&gt;&amp;rdquo; This philosophy drove the team to seek out a solution that would not only streamline their operations but also empower their developers to focus on building innovative products for their customers.&lt;/p&gt;
&lt;h2 id="embracing-pulumi-the-power-of-automation-productivity-and-security"&gt;Embracing Pulumi: The Power of Automation, Productivity, and Security&lt;/h2&gt;
&lt;p&gt;Tivity Health&amp;rsquo;s search for the right tool led them to Pulumi, a unified platform for all the infrastructure needs that allows teams to use general programming languages, such as TypeScript, Python, Java, and Go, to define and manage their cloud infrastructure. Giambruno and his team immediately recognized Pulumi&amp;rsquo;s ability to deliver on their key requirements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Automation&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/iac/"&gt;Pulumi&amp;rsquo;s infrastructure as code (IaC)&lt;/a&gt; approach enabled Tivity Health to automate the deployment and management of its cloud environments, reducing the time and effort required for these tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Productivity&lt;/strong&gt;: using Pulumi&amp;rsquo;s general-purpose programming languages allowed developers to define, deploy, and manage infrastructure within their existing tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security&lt;/strong&gt;: Pulumi&amp;rsquo;s security features allowed Tivity Health to integrate &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;security practices&lt;/a&gt; into its infrastructure deployment processes, reducing the risk of security breaches and ensuring compliance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: Pulumi&amp;rsquo;s ability to automate the spin-up and teardown of cloud environments on demand has led to significant cost reductions for Tivity Health.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Giambruno describes Pulumi as a &amp;ldquo;three-dimensional&amp;rdquo; tool, offering a versatile set of capabilities that have been instrumental in transforming Tivity Health&amp;rsquo;s operations. &amp;ldquo;&lt;em&gt;The ability to use those dimensions in lots of different ways to do the automation is what really makes a difference to the teams&lt;/em&gt;,&amp;rdquo; he says.&lt;/p&gt;
&lt;h2 id="driving-business-impact-through-security-automation"&gt;Driving Business Impact Through Security Automation&lt;/h2&gt;
&lt;p&gt;By adopting Pulumi and DevSecOps automation, Tivity Health realized significant business benefits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed and Agility&lt;/strong&gt;: By automating its infrastructure deployment and management processes, Tivity Health has dramatically &lt;a href="https://www.pulumi.com/case-studies/unity/"&gt;reduced the time&lt;/a&gt; required to spin up new environments or change existing ones. &amp;ldquo;&lt;em&gt;We run it through automation and boom, it&amp;rsquo;s out, it&amp;rsquo;s done&lt;/em&gt;,&amp;rdquo; Giambruno says. This newfound speed and agility have empowered Tivity Health&amp;rsquo;s developers to focus on building products and features rather than getting bogged down in infrastructure-related tasks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cost Optimization&lt;/strong&gt;: Tivity Health&amp;rsquo;s cloud-native approach and Pulumi&amp;rsquo;s automation capabilities have resulted in &lt;a href="https://www.pulumi.com/case-studies/lemonade/"&gt;significant cost savings&lt;/a&gt;. The company estimates that its annual cloud spend has decreased from $9.5 million in its data center days to just $2 million—a staggering 79% reduction. These cost savings have allowed Tivity Health to redirect resources towards more strategic initiatives that drive business growth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Security and Compliance&lt;/strong&gt;: Tivity Health&amp;rsquo;s DevSecOps strategy, anchored by Pulumi, has strengthened its security posture and &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/compliance-ready-policies/"&gt;compliance efforts&lt;/a&gt;. By integrating security directly into its infrastructure workflows, Tivity Health has improved its security posture. Automation ensures that security measures are enforced consistently across their cloud environments, reducing risks and improving compliance.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="fostering-devops-culture-through-cross-functional-collaboration"&gt;Fostering DevOps Culture Through Cross-Functional Collaboration&lt;/h2&gt;
&lt;p&gt;Using Pulumi provided more than technical benefits. It also enabled better collaboration between the development, security, and operations teams. By providing a common language and framework for infrastructure management, Pulumi has helped break down silos and align these traditionally disparate groups towards a shared goal of delivering secure, high-quality products faster.&lt;/p&gt;
&lt;h2 id="lessons-learned-navigating-the-cultural-shift"&gt;Lessons Learned: Navigating the Cultural Shift&lt;/h2&gt;
&lt;p&gt;Transitioning to DevSecOps and cloud-native practices required a cultural shift at Tivity Health. Giambrono acknowledges that this cultural shift was not without its challenges. He emphasizes the importance of addressing the human element of change, offering the following advice for organizations embarking on a similar journey:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Start with a proof of concepts&lt;/strong&gt;: Giambruno recommends beginning with a small-scale proof of concepts to demonstrate the capabilities and benefits of the new technologies and processes to help alleviate fears and build confidence among team members.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empower developers and make them feel safe&lt;/strong&gt;: By involving developers in the process and ensuring they feel comfortable with the new tools and workflows, Tivity Health gained user buy-in and overall support for the new DevSecOps approach.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure buy-in from business and financial stakeholders&lt;/strong&gt;: Address the concerns of business and financial stakeholders early on, such as the impact on costs and the ability to deliver tangible results. This is crucial for securing the necessary support and resources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Celebrate successes and build momentum&lt;/strong&gt;: Giambruno highlights the importance of celebrating the team&amp;rsquo;s achievements along the way, even when there are bumps on the road, as this helps build enthusiasm and keep the momentum going.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-future-of-devsecops-and-pulumi-at-tivity-health"&gt;The Future of DevSecOps and Pulumi at Tivity Health&lt;/h2&gt;
&lt;p&gt;As Tivity Health continues to refine its DevSecOps strategy, Giambruno is optimistic about the future. He envisions a world where the company&amp;rsquo;s ability to deploy new products and features rapidly will give Tivity Health a significant competitive edge, allowing it to better serve its customers and drive business growth.&lt;/p&gt;
&lt;p&gt;Looking ahead, Giambruno is particularly enthusiastic about the potential of Pulumi&amp;rsquo;s AI-powered capabilities, which he believes will further streamline and optimize the company&amp;rsquo;s infrastructure management processes. &amp;ldquo;&lt;em&gt;I&amp;rsquo;m super looking forward to the tests we&amp;rsquo;re going to do, like when we acquire someone and then taking them in, &amp;lsquo;Borg-ing&amp;rsquo; them into our automation and seeing how much we can take out of their operating cost as fast as possible&lt;/em&gt;,&amp;rdquo; he says.&lt;/p&gt;
&lt;p&gt;Tivity Health&amp;rsquo;s journey with Pulumi is a powerful example of how the right tool, DevSecOps strategy, and automation can drive tangible business results. By focusing on automation, security, and collaboration, organizations can achieve faster, cheaper, and better cloud deployments—putting them on the path to long-term success in an increasingly competitive, cloud-native world.&lt;/p&gt;
&lt;p&gt;To learn more about Pulumi and how it can transform your software development and infrastructure management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with &lt;a href="https://www.pulumi.com/tutorials/"&gt;Pulumi Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Attend an &lt;a href="https://www.pulumi.com/resources/#upcoming"&gt;upcoming workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Try out the &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; code assistant to accelerate your infrastructure as code journey&lt;/li&gt;
&lt;/ul&gt;</description><author>Sara Huddleston</author><category>security</category><category>devsecops</category><category>devops</category><category>infrastructure-as-code</category><category>platform-engineering</category><category>infrastructure-lifecycle-management</category><category>developer-experience</category></item><item><title>Pulumi Patterns and Practices Platform (P3): Some Assembly Required</title><link>https://www.pulumi.com/blog/p3-some-assembly-required/</link><pubDate>Mon, 11 Nov 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/p3-some-assembly-required/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/p3-some-assembly-required/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Setting up an internal developer platform (IDP) can be a daunting task. There are a lot of tools out there that do some of the work for you, but none of them do all of it. Pulumi P3 is no different. Pulumi Patterns &amp;amp; Practices Platform (P3) is a &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;reference architecture&lt;/a&gt; that we will be describing, and providing code for, through this series of articles.&lt;/p&gt;
&lt;p&gt;We will never try to sell you on the idea that you can simply download a package, click next a few times, and achieve transformative success. That’s because any effective IDP will require some customization and integration to work within your environment.&lt;/p&gt;
&lt;p&gt;Tools that purport to have it all figured out have only figured out how to manipulate you into a false narrative they have constructed in a vacuum, where all your organizational needs fit neatly into a few boxes they’ve decided on for you. And also charge you for. In addition to everything else you’re being charged for. Ultimately you’ll still need to build a lot yourself and these products rarely give guidance on how to do that.&lt;/p&gt;
&lt;p&gt;When we first started hearing about our customers using Pulumi as an internal developer platform (IDP), we were frankly surprised, as our goals were primarily for Pulumi to be the best developer experience in infrastructure. But it makes sense. All the parts are there, some assembly required. Our goal with Pulumi Patterns and Practices Platform (P3) is to help with that assembly process.&lt;/p&gt;
&lt;p&gt;Starting with our &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/"&gt;previous blog post&lt;/a&gt; on the topic, and continuing here, we are examining this use case, and attempting to formalize that into a collection of reusable components and some guidance on how you can skip the marketing pitches and pricing charts, and get straight to the hard work of building your own highly customized internal developer platform with Pulumi at its core.&lt;/p&gt;
&lt;h2 id="pulumi-p3-bill-of-materials"&gt;Pulumi P3: Bill of Materials&lt;/h2&gt;
&lt;p&gt;Previously we identified the &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#an-effective-internal-developer-platform"&gt;essential qualities of an effective IDP&lt;/a&gt;. Those were consistency, reproducibility, visibility, security and compliance, auditability, developer experience. In the &lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#a-holistic-view-of-the-patterns-and-practices-platform-reference-architecture"&gt;last half of the post&lt;/a&gt; we discussed which parts of Pulumi could be used to meet those needs. That looks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/learn/abstraction-encapsulation/component-resources/"&gt;component resources&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;organization templates&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/"&gt;drift detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reproducibility&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/understanding-stacks/"&gt;stacks&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;deployments&lt;/a&gt;, &lt;a href="https://www.pulumi.com/registry/packages/snowflake/api-docs/dynamictable/"&gt;versioned data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visibility&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/copilot/"&gt;Pulumi Copilot&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security and Compliance&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/"&gt;RBAC&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;GitHub Teams&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;SAML-SSO&lt;/a&gt;, &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC&lt;/a&gt;, &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi Crossguard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Auditability&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/"&gt;audit logging&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;: &lt;a href="https://www.pulumi.com/docs/languages-sdks/"&gt;Python/Go/JavaScript/C#&lt;/a&gt;, &lt;a href="https://www.pulumi.com/blog/next-level-iac-breakpoint-debugging/"&gt;popular IDE support&lt;/a&gt;, &lt;a href="https://www.pulumi.com/docs/cli/"&gt;command-line tools&lt;/a&gt;, &lt;a href="https://www.pulumi.com/automation/"&gt;deeply hackable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s all great, and much of that is already built-into Pulumi without the need for you to do anything at all. So, what parts do you actually need to set up and configure? Here’s the bill of materials (BOM) to set up your own instance of Pulumi P3:&lt;/p&gt;
&lt;h3 id="bill-of-materials"&gt;Bill of Materials:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Authentication and Identity Management&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A GitHub organization that matches your Pulumi Cloud organization&lt;/li&gt;
&lt;li&gt;GitHub Teams users and roles that match your organizational structure and security needs&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secrets, Configuration, and Policy&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pulumi ESC environments to manage secrets across clouds&lt;/li&gt;
&lt;li&gt;Pulumi Crossguard policy packs that capture your company policies&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Developer Experience&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A set of reusable multi-language components for cross-cutting concerns/common services&lt;/li&gt;
&lt;li&gt;A set of organization templates that match your common use cases&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let’s go through each of those and briefly discuss what it looks like to set that up.&lt;/p&gt;
&lt;h2 id="authentication-and-identity-management"&gt;Authentication and identity management&lt;/h2&gt;
&lt;p&gt;We highly recommend using GitHub for code management. So much so that we have deeply integrated GitHub into Pulumi Cloud across a number of features. While we support &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/organizations/#gitlab-identity-provider"&gt;alternatives such as GitLab&lt;/a&gt;, this will be the easiest and more feature-rich way to configure your platform.&lt;/p&gt;
&lt;p&gt;In Pulumi Cloud, you have the ability to create organizations. A &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/organizations/"&gt;Pulumi Cloud organization&lt;/a&gt; can help you manage teams, roles, stacks, settings, and provide a dashboard across the entire organization. Pulumi Cloud also allows you to use a variety of identity providers to log in, including GitHub.&lt;/p&gt;
&lt;p&gt;For simplicity’s sake, we suggest that you start with your GitHub organization. &lt;a href="https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/creating-a-new-organization-from-scratch"&gt;Create the GitHub organization&lt;/a&gt;, &lt;a href="https://docs.github.com/en/organizations/organizing-members-into-teams/about-teams"&gt;set up teams&lt;/a&gt;, and &lt;a href="https://docs.github.com/en/organizations/organizing-members-into-teams/adding-organization-members-to-a-team"&gt;add members&lt;/a&gt; to those teams, assigning either admin or user &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/using-organization-roles"&gt;roles&lt;/a&gt; to each member.&lt;/p&gt;
&lt;p&gt;Next, in Pulumi Cloud, create an organization &lt;em&gt;&lt;strong&gt;with exactly the same name&lt;/strong&gt;&lt;/em&gt; as your GitHub organization, and choose GitHub as your identity provider. When a Pulumi organization is backed by a GitHub organization, then only members of that GitHub organization may be added to the Pulumi organization. Similarly, as soon as someone loses access to the GitHub organization, they will no longer have access to the Pulumi organization. You will also be able to &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;import your GitHub teams&lt;/a&gt; directly into Pulumi Cloud. Then assign your users to the same roles in Pulumi Cloud teams as they have in the associated GitHub teams.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/p3-some-assembly-required/teams-gh-pulumi.png"
alt="Figure: Mapping GitHub orgs, teams, and roles to Pulumi"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Mapping GitHub orgs, teams, and roles to Pulumi&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Finally, you can &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#granting-access-to-stacks-within-teams"&gt;map teams to stacks&lt;/a&gt; to grant access at specific permission levels. If you’re not familiar with &lt;a href="https://www.pulumi.com/docs/concepts/stack/"&gt;Pulumi Stacks&lt;/a&gt;, a stack is a materialized instance of a specific set of cloud resources, as defined in a Pulumi program.&lt;/p&gt;
&lt;h2 id="pulumi-esc-managing-credentials-configuration-and-other-secrets"&gt;Pulumi ESC: Managing credentials, configuration, and other secrets&lt;/h2&gt;
&lt;p&gt;In order to deploy a stack you will need secrets such as cloud credentials and other configuration values that are provided to the deployment engine. Pulumi ESC is a secure system for managing secrets. They are organized by &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/environments/"&gt;environments&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;An example set of environments might look something like this:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; AWS login/credentials&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-creds ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;fn::open::aws-login&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;oidc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;roleArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;arn:aws:iam::123456789012:role/pulumi-environments-oidc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;sessionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;pulumi-environments-session&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;1h&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;environmentVariables&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_ACCESS_KEY_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.accessKeyId}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_SECRET_ACCESS_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.secretAccessKey}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;AWS_SESSION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.creds.sessionToken}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Default production environment to use &lt;code&gt;us-east-1&lt;/code&gt; region&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-production ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-east-1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pulumiConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws:region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.region}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Default staging environment to use &lt;code&gt;us-west-2&lt;/code&gt; region&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# aws-staging ESC environment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-creds&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;us-west-2&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;pulumiConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;aws:region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${aws.region}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we define three environments for AWS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;aws-creds&lt;/code&gt;: sets up login via OpenID Connect (OIDC) and provides standard environment variables containing AWS credentials to the Pulumi program&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws-production&lt;/code&gt;: imports everything from &lt;code&gt;aws-creds&lt;/code&gt; then sets the region to &lt;code&gt;us-east-1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;aws-staging&lt;/code&gt;: does the same, but sets the region to &lt;code&gt;us-west-2&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Using that in a Pulumi program is as simple as adding the following settings to your stack config:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.staging.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-staging&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this manner, you can configure separate environments for staging and production, with a complex set of configuration values and secrets, using different environments for each one. From the developer’s perspective they would only need to change &lt;code&gt;aws-staging&lt;/code&gt; to &lt;code&gt;aws-production&lt;/code&gt; when they go to deploy their stack.&lt;/p&gt;
&lt;p&gt;Another strong benefit of this approach is that all secrets will be encrypted both in-flight and at-rest. Pulumi waits until the last moment to decrypt secrets at runtime. By default, uses automatic, per-stack encryption keys provided by Pulumi Cloud, but you could use a &lt;a href="https://www.pulumi.com/docs/concepts/secrets/#configuring-secrets-encryption"&gt;provider of your own choosing&lt;/a&gt; instead.&lt;/p&gt;
&lt;h2 id="pulumi-crossguard-policy-as-code"&gt;Pulumi Crossguard: Policy-as-Code&lt;/h2&gt;
&lt;p&gt;Pulumi Crossguard allows you to check and enforce policies on your deployments. Policies are rules, written in code, that run during deployments to check that the resources are conforming to the necessary criteria. You can use off-the-shelf policies like &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/awsguard"&gt;AWSGuard&lt;/a&gt; and &lt;a href="https://github.com/pulumi/compliance-policies/"&gt;Pulumi Compliance-Ready Policies&lt;/a&gt; or write your own.&lt;/p&gt;
&lt;p&gt;Either way you end up with a &lt;em&gt;policy pack&lt;/em&gt; that you can apply to your entire Pulumi organization via Pulumi Cloud.&lt;/p&gt;
&lt;p&gt;Here’s an example policy that checks for the presence of a tag &lt;code&gt;user:Stack&lt;/code&gt; on a S3 bucket:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_policy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;PolicyPack&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;s3_check_required_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;aws:s3/bucket:Bucket&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;user:Stack&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;report_violation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;S3 Bucket is missing required user:Stack tag.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;PolicyPack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;bucket-tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;enforcement_level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;EnforcementLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MANDATORY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;policies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceValidationPolicy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;s3-tags&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Ensure required tags are present on S3 buckets.&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;s3_check_required_tags&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the tag isn&amp;rsquo;t on the resource, it blocks the deployment with an error message. The error message would look something like this:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;Policies:
❌ bucket-tags@v0.0.1
- [mandatory] s3-tags (aws:s3/bucket:Bucket: my-bucket)
Ensure required tags are present on S3 buckets.
S3 Bucket is missing required user:Stack tag.
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows you to implement company-specific policies that can be as simple or complex as you need them to be.&lt;/p&gt;
&lt;p&gt;To apply this across your entire organization, you can &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/get-started/#enforcing-a-policy-pack"&gt;publish this policy pack to Pulumi Cloud&lt;/a&gt;, with the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi policy publish myorg
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ pulumi policy &lt;span class="nb"&gt;enable&lt;/span&gt; myorg/my-policy-pack latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Some other great features of Crossguard are the ability to &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/faq/#how-do-i-version-a-policy-pack"&gt;version policies&lt;/a&gt;, define multiple &lt;a href="https://www.pulumi.com/docs/using-pulumi/crossguard/core-concepts/#policy-groups"&gt;policy groups&lt;/a&gt;, and create &lt;a href="https://www.pulumi.com/blog/remediation-policies/"&gt;remediation policies&lt;/a&gt; that automatically fix policy violations when possible. We will cover these topics in a future post where we go deeper on how to use policies effectively.&lt;/p&gt;
&lt;h2 id="multi-language-components-mlc"&gt;Multi-Language Components (MLC)&lt;/h2&gt;
&lt;p&gt;In Pulumi, a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/resources/components/"&gt;component resource&lt;/a&gt;&lt;/em&gt; is something that your developers can import in their Pulumi program, instantiate and modify. These are made available via a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/concepts/resources/providers/"&gt;provider&lt;/a&gt;&lt;/em&gt;, which is in turn, made available to Pulumi via a &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/using-pulumi/pulumi-packages/"&gt;provider package&lt;/a&gt;&lt;/em&gt;. There are many of these already available in the &lt;a href="https://www.pulumi.com/registry/"&gt;Pulumi Registry&lt;/a&gt;. However, in a custom internal developer platform you can define your own components, and bake appropriate settings/configuration directly into the underlying code.&lt;/p&gt;
&lt;p&gt;A &lt;em&gt;multi-language component (MLC)&lt;/em&gt; is even more useful. You can author your component in your language of choice and then generate a SDK that surfaces that component into all of the languages that Pulumi supports. For example, your platform team might be comfortable writing in Python, but the developers that write your microservices might use Go, and the developers who write the front-end apps might use Node.js. Both teams might need to deploy apps and infrastructure into your Kubernetes cluster. With multi-language components you can write a component in Python that abstracts away all the details of your custom Kubernetes cluster, and make that available to both teams, in both Go, Node.js, and any other language that Pulumi supports.&lt;/p&gt;
&lt;p&gt;To build a MLC, you&amp;rsquo;ll follow these basic steps to create the component, provider, provider package, and generate the multi-language SDK:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Fork one of the component provider boilerplate repos for &lt;a href="https://github.com/pulumi/pulumi-component-provider-py-boilerplate"&gt;Python&lt;/a&gt;, &lt;a href="https://github.com/pulumi/pulumi-component-provider-ts-boilerplate"&gt;TypeScript&lt;/a&gt;, or &lt;a href="https://github.com/pulumi/pulumi-component-provider-go-boilerplate"&gt;Go&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Update the package and code-generator configuration files, which name your component and package, define the inputs and outputs, and declare the dependencies.&lt;/li&gt;
&lt;li&gt;Implement the component in your preferred language.&lt;/li&gt;
&lt;li&gt;Generate an SDK for the other languages.&lt;/li&gt;
&lt;li&gt;Deploy the package.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s a quick example of creating a custom S3 Bucket component in Python, that complies with the tagging policy we built earlier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;pulumi_aws&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ComponentResource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;mycorp:index:TaggedBucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Create a bucket and add a custom tag to it.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;-bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;user:Stack&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_stack&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ResourceOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;register_outputs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;websiteUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;website_endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;bucketDnsName&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucketDomainName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This shows the component implementation in isolation from the provider/packaging/SDK boilerplate. In this code sample, we’re creating a component called &lt;code&gt;TaggedBucket&lt;/code&gt; that creates a S3 bucket, and adds a tag &lt;code&gt;user:Stack&lt;/code&gt; with the current stack name as its value. A developer could now use this in a TypeScript Pulumi program as such, and this resource would automatically have the tags added to it.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-javascript" data-lang="javascript"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;mycorp&lt;/span&gt; &lt;span class="nx"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mycorp/mycorp-components&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mycorp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;example&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;websiteUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kr"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dnsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;taggedBucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bucketDnsName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you want to see how to create MLCs in more detail, check out &lt;a href="https://www.youtube.com/watch?v=_RXvNS5N8A8"&gt;this video&lt;/a&gt; that walks you through the entire process, and &lt;a href="https://github.com/jaxxstorm/pulumi-productionapp"&gt;this repo&lt;/a&gt; for the code shown in the video. In a follow-up post in this series, we will build some reference MLCs that do things like implement a time-to-live (TTL) for stacks in your staging environment, automate drift detection, and automatically instrument your developer’s deployments with observability tools integrated by default.&lt;/p&gt;
&lt;h2 id="organization-templates-and-the-new-project-wizard"&gt;Organization templates and the New Project Wizard&lt;/h2&gt;
&lt;p&gt;The final piece that ties all this together are &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;organization templates&lt;/a&gt;&lt;/em&gt;. You may have used some of our &lt;a href="https://www.pulumi.com/templates/"&gt;built-in templates&lt;/a&gt; when you learned how to use Pulumi. These are great for basic use cases, but the real magic happens when you bring together your custom components and custom security environments to create personalized templates which represent the internal use cases for your organization.&lt;/p&gt;
&lt;p&gt;Pulumi’s &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/new-project-wizard/"&gt;New Project Wizard&lt;/a&gt; reads these templates and provides an in-browser way to create a new project and deploy it. Running one of these templates will commit and push code to GitHub, and trigger an initial deployment – all in a few clicks and without leaving the browser.&lt;/p&gt;
&lt;p&gt;Each template needs the following parts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;Pulumi.yaml&lt;/code&gt; describing the template and its configuration values&lt;/li&gt;
&lt;li&gt;A GitHub repo (public or private) containing the code for the templated Pulumi program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here’s an example of a simple template using the components and environments we described above.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${PROJECT}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${DESCRIPTION}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;python&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;A Python Pulumi program that creates a tagged bucket.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;__main__.py: A minimal Pulumi program&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pulumi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;mycorp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Create an AWS resource (S3 Bucket)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tagged_bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mycorp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TaggedBucket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;my-bucket&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Export the name of the bucket&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pulumi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;bucket_name&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tagged_bucket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.production.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-production&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Pulumi.staging.yaml&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;aws-staging&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Pulumi.yaml&lt;/code&gt; sets up the template and will populate the name and description from the settings provided during the template dialogue. The custom &lt;code&gt;TaggedBucket&lt;/code&gt; component will create an S3 bucket, which will be tagged with &lt;code&gt;user:Stack&lt;/code&gt; set to the name of the stack. Default stack configurations are provided for the &lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; environments which map to our two ESC environments, &lt;code&gt;aws-production&lt;/code&gt; and &lt;code&gt;aws-staging&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id="how-it-all-works-together"&gt;How it all works together&lt;/h2&gt;
&lt;p&gt;With all of that in place, from the developer’s perspective, all they need to do is create a new project from the template, answering three questions: the stack name, the name of the project, and an optional description.&lt;/p&gt;
&lt;p&gt;If the developer names the stack &lt;code&gt;staging&lt;/code&gt; it will automatically apply the &lt;code&gt;aws-staging&lt;/code&gt; ESC environment, which will include the AWS credentials and set the region to &lt;code&gt;us-west-2&lt;/code&gt;. However, if the developer names the stack &lt;code&gt;production&lt;/code&gt; it will get the &lt;code&gt;aws-production&lt;/code&gt; ESC environment setting it to use the &lt;code&gt;us-east-1&lt;/code&gt; region. The name of the stack will be stored in a tag on the resource.&lt;/p&gt;
&lt;p&gt;Pulumi Crossguard will apply the &lt;code&gt;bucket-tags&lt;/code&gt; policy check to see if the resource has the required &lt;code&gt;user:Stack&lt;/code&gt; tag set and will allow the deployment to proceed only if it has that tag. If a developer created a standard S3 Bucket instead of using our internal &lt;code&gt;TaggedBucket&lt;/code&gt; component, and failed to add the required tag, they will get an error message from our custom policy when they try to deploy.&lt;/p&gt;
&lt;p&gt;Later, we can create additional automation that might do something like delete anything tagged &lt;code&gt;staging&lt;/code&gt; after two weeks, or run drift detection on anything tagged &lt;code&gt;production&lt;/code&gt;. We will be exploring these concepts in more detail in later posts.&lt;/p&gt;
&lt;h3 id="more-to-come"&gt;More to Come&lt;/h3&gt;
&lt;p&gt;While setting up the Pulumi Patterns and Practices Platform (P3) reference architecture is not a simple click-to-deploy, hopefully this high-level tour of the various parts you need to assemble shows that really, it is only a matter of creating a few carefully constructed YAML files and snippets of code, and wiring them together properly. You can start small and build out your platform over time.&lt;/p&gt;
&lt;p&gt;The next few posts in this series will go beyond these simple examples, showing much more complicated implementations of all of these pieces, and recommend some best practices for managing your infrastructure with this platform.&lt;/p&gt;
&lt;p&gt;And if you are already ready to get your hands on Pulumi after this introduction, feel free to &lt;a href="https://www.pulumi.com/signup/"&gt;create an account&lt;/a&gt; and follow some of our &lt;a href="https://www.pulumi.com/docs/get-started/"&gt;Getting Started&lt;/a&gt; guides to see how easy simple use cases are and begin to imagine how that same developer experience will scale up to your entire organization.&lt;/p&gt;
&lt;p&gt;To learn more, you can watch the following video which provides a high level overview of how Pulumi works:&lt;/p&gt;
&lt;div class="rounded-md shadow border border-gray-300 w-3/4 mx-auto my-4" style="position: relative; padding-bottom: 40.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe
src="//www.youtube.com/embed/Q8tw6YTD3ac?rel=0"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen=""
title="Introduction to Pulumi in Three Minutes"
srcdoc="&lt;style&gt;*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img{position:absolute;width:100%;top:0;bottom:0;margin:auto}&lt;/style&gt;&lt;a href=https://www.youtube.com/embed/Q8tw6YTD3ac?autoplay=1&gt;&lt;img src='https://www.pulumi.com/images/home/youtube-getting-started.png' alt='Introduction to Pulumi in Three Minutes'&gt;&lt;/a&gt;"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="pulumi-cloud"&gt;Pulumi Cloud&lt;/h2&gt;
&lt;p&gt;The Pulumi Cloud is a fully managed service that helps you adopt Pulumi&amp;rsquo;s open source SDK with ease. It provides built-in state and secrets management, integrates with source control and CI/CD, and offers a web console and API that make it easier to visualize and manage infrastructure. It is free for individual use, with features available for teams.&lt;/p&gt;
&lt;p&gt;&lt;a class="btn btn-secondary" href="https://app.pulumi.com/signup" target="_blank"&gt;Create an Account&lt;/a&gt;&lt;/p&gt;</description><author>Troy Howard</author><category>platform-engineering</category><category>patterns-and-practices-platform</category><category>developer-experience</category><category>devsecops</category><category>architecture</category><category>enterprise</category><category>devops</category></item><item><title>Unified and Programmatic Approach to Infrastructure Management at BMW Using Pulumi</title><link>https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/</link><pubDate>Thu, 03 Oct 2024 09:52:10 +0000</pubDate><guid>https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/index.png" /&gt;
&lt;p&gt;In the ever-evolving world of automotive technology, BMW has been at the forefront of innovation, seamlessly integrating software into the heart of their vehicles. As cars become increasingly complex, with a growing emphasis on connectivity, over-the-air upgrades, and brand-specific user experiences, the need for a robust and scalable software development approach has become paramount.&lt;/p&gt;
&lt;p&gt;Enter the BMW Software Factory, a platform that aims to empower the company&amp;rsquo;s developers and provide them with a superior development experience. At the core of this initiative is the adoption of Pulumi, a modern infrastructure as code (IaC) solution that has transformed the way BMW manages its software ecosystem.&lt;/p&gt;
&lt;h2 id="on-this-article"&gt;On this article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-challenges-of-a-sprawling-software-landscape"&gt;The Challenges of a Sprawling Software Landscape&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-evolution-of-bmws-software-development-toolchain"&gt;The Evolution of BMW&amp;rsquo;s Software Development Toolchain&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#embracing-pulumi-streamlining-infrastructure-management"&gt;Embracing Pulumi: Streamlining Infrastructure Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-benefits-of-pulumi-accelerating-development-and-improving-maintainability"&gt;The Benefits of Pulumi: Accelerating Development and Improving Maintainability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#the-future-of-bmws-software-factory-embracing-the-cloud"&gt;The Future of BMW&amp;rsquo;s Software Factory: Embracing the Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/unified-programmatic-approach-infrastructure-management-bmw-using-pulumi/#conclusion-unlocking-the-future-of-automotive-software"&gt;Conclusion: Unlocking the Future of Automotive Software&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-challenges-of-a-sprawling-software-landscape"&gt;The Challenges of a Sprawling Software Landscape&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/HIliBBo4c-g?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.bmwgroup.com/en/news/general/2023/BMWGroupIT.html"&gt;BMW&amp;rsquo;s software journey&lt;/a&gt; has been a testament to the exponential growth of automotive technology. What started with simple engine controllers has evolved into a complex network of electronic control units (ECUs) scattered throughout the vehicle. As the software footprint continues to expand, BMW recognized the need for a unified and efficient approach to software development and deployment.&lt;/p&gt;
&lt;p&gt;The company&amp;rsquo;s initial efforts involved introducing a platform called &amp;ldquo;Code Craft,&amp;rdquo; which provided a comprehensive stack of services to support the software development lifecycle. This stack included a GitHub Enterprise application for source code management, a Gerrit system for Android-based developments, a continuous integration (CI) pipeline, artifact stores, build caching, and various other tools and services.&lt;/p&gt;
&lt;p&gt;However, as the demand for software-driven features grew, the complexity of managing this sprawling ecosystem became increasingly challenging. BMW found itself grappling with the need to scale its infrastructure, navigate network limitations across multiple data centers, and adapt to the ever-changing landscape of cloud computing.&lt;/p&gt;
&lt;h2 id="the-evolution-of-bmws-software-development-toolchain"&gt;The Evolution of BMW&amp;rsquo;s Software Development Toolchain&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s journey to streamline its software development process has been gradual and iterative. The company&amp;rsquo;s initial approach involved using &lt;a href="https://www.pulumi.com/docs/iac/comparisons/chef-puppet-etc/"&gt;Ansible&lt;/a&gt; for deployment and a custom-built deployment scripting solution for its OpenShift cluster.&lt;/p&gt;
&lt;p&gt;As the complexity of the platform increased, BMW turned to Helm and Kubernetes to manage its containerized services. However, as the company ventured into the public cloud, the limitations of these tools became apparent. The team recognized the need for a more comprehensive and scalable solution to manage their infrastructure as code.&lt;/p&gt;
&lt;p&gt;At this critical juncture, BMW discovered Pulumi. This modern IaC solution offered a unique advantage – the ability to leverage a full-fledged programming language, Python, to define and manage their infrastructure. This shift proved to be a game-changer, allowing BMW to leverage its expertise in Python and benefit from the rich ecosystem of libraries and tools available in the Python community.&lt;/p&gt;
&lt;h2 id="embracing-pulumi-streamlining-infrastructure-management"&gt;Embracing Pulumi: Streamlining Infrastructure Management&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/case-studies/bmw/"&gt;BMW&amp;rsquo;s adoption of Pulumi&lt;/a&gt; was a strategic move that aimed to address the growing complexity of its software ecosystem. By transitioning from a patchwork of tools to a unified IaC solution, the company was able to streamline its infrastructure management and improve developer productivity.&lt;/p&gt;
&lt;h3 id="shared-modules-promoting-reusability-and-best-practices"&gt;Shared Modules: Promoting Reusability and Best Practices&lt;/h3&gt;
&lt;p&gt;One of BMW&amp;rsquo;s key initiatives was developing a shared modules library, which allowed the team to abstract the complexity of various infrastructure components, such as databases, and provide a consistent and user-friendly interface for their developers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By leveraging &lt;a href="https://www.pulumi.com/docs/iac/languages-sdks/python/"&gt;Pulumi&amp;rsquo;s Python&lt;/a&gt; bindings, BMW was able to create reusable modules that encapsulated best practices and sensible defaults, making it easier for developers to provision and manage infrastructure resources.
BMW used Pydantic, a data validation library, to define schema-based configurations for its infrastructure. These were then integrated into its IDEs, providing developers with auto-completion and validation support.&lt;/li&gt;
&lt;li&gt;This approach not only accelerated the development process but also ensured that the infrastructure deployed across the organization adhered to consistent security and compliance standards.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="transformation-features-protecting-legacy-services"&gt;Transformation Features: Protecting Legacy Services&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;As part of their software factory, BMW also faced the challenge of integrating legacy services that did not natively support modern authentication and authorization mechanisms, such as &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/oidc/provider/"&gt;OpenID Connect (OIDC)&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;To address this, BMW leveraged Pulumi&amp;rsquo;s transformation features to seamlessly inject an &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/oidc/client/#exchanging-oidc-tokens"&gt;OAuth2&lt;/a&gt; proxy into their deployments, providing a secure and consistent way to protect these services without requiring extensive modifications to the underlying applications.&lt;/li&gt;
&lt;li&gt;By encapsulating this functionality within a shared module, BMW was able to apply the OAuth2 proxy to multiple services, ensuring a consistent and secure access control layer across their software ecosystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="policy-enforcement-ensuring-compliance-and-security"&gt;Policy Enforcement: Ensuring Compliance and Security&lt;/h3&gt;
&lt;p&gt;One key benefit of &lt;a href="https://www.pulumi.com/product/infrastructure-as-code/"&gt;Pulumi&amp;rsquo;s IaC approach&lt;/a&gt; is the ability to define and enforce policies across the organization, ensuring that infrastructure deployments adhere to security and compliance standards.
BMW has leveraged &lt;a href="https://www.pulumi.com/docs/iac/packages-and-automation/crossguard/"&gt;Pulumi&amp;rsquo;s policy-as-code&lt;/a&gt; capabilities to implement mandatory checks, such as ensuring that all S3 buckets are encrypted at rest, preventing the deployment of non-compliant resources.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;By integrating these policy checks into their deployment workflows, BMW has shifted security and compliance concerns to the left, addressing issues early in the development process and reducing the risk of costly post-deployment &lt;a href="https://www.pulumi.com/blog/remediation-policies/"&gt;remediations&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-benefits-of-pulumi-accelerating-development-and-improving-maintainability"&gt;The Benefits of Pulumi: Accelerating Development and Improving Maintainability&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s adoption of Pulumi has yielded significant benefits, transforming the way the company approaches software development and infrastructure management.&lt;/p&gt;
&lt;h3 id="accelerated-development-with-shared-modules"&gt;Accelerated Development with Shared Modules&lt;/h3&gt;
&lt;p&gt;The implementation of shared modules has been a game-changer for BMW. It allows developers to leverage pre-built and tested infrastructure components without having to reinvent the wheel. This has resulted in a significant acceleration of the development process, as teams can focus on building their applications rather than grappling with the complexities of infrastructure provisioning.&lt;/p&gt;
&lt;h3 id="improved-maintainability-and-consistency"&gt;Improved Maintainability and Consistency&lt;/h3&gt;
&lt;p&gt;By centralizing infrastructure management within the shared modules, BMW has ensured that best practices and security standards are consistently applied across the organization. This has not only improved the overall maintainability of the software ecosystem but has also reduced the risk of security and compliance violations.&lt;/p&gt;
&lt;h3 id="leveraging-pythons-ecosystem"&gt;Leveraging Python&amp;rsquo;s Ecosystem&lt;/h3&gt;
&lt;p&gt;BMW&amp;rsquo;s decision to leverage Pulumi&amp;rsquo;s Python bindings has been a strategic advantage, as the company was able to tap into the rich ecosystem of Python libraries and tools. This has enabled the team to seamlessly integrate Pulumi with their existing Python-based toolchain, including dependency management, testing frameworks, and code quality tools, further enhancing the development experience.&lt;/p&gt;
&lt;h3 id="streamlined-cloud-migration"&gt;Streamlined Cloud Migration&lt;/h3&gt;
&lt;p&gt;As BMW continues to expand its use of public cloud services, Pulumi has played a crucial role in simplifying the &lt;a href="https://www.pulumi.com/migrate/"&gt;migration process&lt;/a&gt;. By providing a consistent IaC approach across on-premises and cloud environments, Pulumi has enabled BMW to manage its infrastructure in a unified manner, reducing the complexity and overhead associated with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;multi-cloud deployments&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-future-of-bmws-software-factory-embracing-the-cloud"&gt;The Future of BMW&amp;rsquo;s Software Factory: Embracing the Cloud&lt;/h2&gt;
&lt;p&gt;Looking ahead, BMW&amp;rsquo;s Software Factory is poised to take the next step in its evolution, with plans to transition away from the self-hosted backend and embrace cloud-native services. This strategic move aims to further improve &lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/"&gt;developer productivity&lt;/a&gt; and reduce the internal effort required to maintain the underlying infrastructure.&lt;/p&gt;
&lt;p&gt;By leveraging the expertise and reliability of cloud service providers, BMW can focus on delivering innovative software features to their customers while the cloud providers handle the operational aspects of running the necessary services.&lt;/p&gt;
&lt;p&gt;As BMW continues to push the boundaries of automotive software, Pulumi&amp;rsquo;s role in its Software Factory will only become more crucial. By providing a scalable and flexible IaC solution, Pulumi empowers BMW&amp;rsquo;s developers to innovate with confidence and be secure in the knowledge that their infrastructure is managed consistently and in alignment with the company&amp;rsquo;s &lt;a href="https://www.pulumi.com/resources/security-automation-faster-cheaper-better/"&gt;security and compliance standards&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="conclusion-unlocking-the-future-of-automotive-software"&gt;Conclusion: Unlocking the Future of Automotive Software&lt;/h2&gt;
&lt;p&gt;BMW&amp;rsquo;s journey with Pulumi in the Software Factory showcases the power of modern IaC solutions in navigating the complexities of the automotive software landscape. By embracing a unified and programmatic approach to infrastructure management, BMW has accelerated development, improved maintainability, and ensured compliance across its sprawling software ecosystem.&lt;/p&gt;
&lt;p&gt;As the automotive industry continues to evolve, with cars becoming increasingly software-driven, the lessons learned by BMW can serve as a blueprint for other organizations looking to streamline their software development and deployment processes. By leveraging the capabilities of Pulumi and other cutting-edge technologies, the future of automotive software is poised to be more efficient, secure, and responsive to the ever-changing needs of both manufacturers and consumers.&lt;/p&gt;
&lt;p&gt;To learn more about Pulumi and how it can transform your software development and infrastructure management:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get started with &lt;a href="https://www.pulumi.com/tutorials/"&gt;Pulumi Tutorials&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Attend an &lt;a href="https://www.pulumi.com/resources/#upcoming"&gt;upcoming workshop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Try out the &lt;a href="https://www.pulumi.com/product/neo/"&gt;Pulumi Neo&lt;/a&gt; code assistant to accelerate your infrastructure as code journey&lt;/li&gt;
&lt;/ul&gt;</description><author>Sara Huddleston</author><category>infrastructure-as-code</category><category>cloud-management</category><category>infrastructure-lifecycle-management</category><category>platform-engineering</category><category>developer-experience</category><category>ansible</category><category>containers</category><category>pulumi-deployments</category></item><item><title>AWS CDK vs Pulumi: Why SST Chose Pulumi</title><link>https://www.pulumi.com/blog/aws-cdk-vs-pulumi-why-sst-switched/</link><pubDate>Wed, 25 Sep 2024 07:32:40 +0000</pubDate><guid>https://www.pulumi.com/blog/aws-cdk-vs-pulumi-why-sst-switched/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/aws-cdk-vs-pulumi-why-sst-switched/index.png" /&gt;
&lt;p&gt;Cloud computing tools evolve, and so must the frameworks developers rely on. For SST (Serverless Stack), AWS CDK was a great starting point—but it had limitations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CDK tied infrastructure to AWS.&lt;/li&gt;
&lt;li&gt;Debugging was frustrating due to CloudFormation templates.&lt;/li&gt;
&lt;li&gt;Multi-cloud was nearly impossible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The solution? Pulumi. In this post, we’ll explore why SST moved to Pulumi, what challenges they overcame, and what this means for developers building modern cloud applications.&lt;/p&gt;
&lt;p&gt;TL;DR: Pulumi lets SST offer a faster, more flexible, and provider-agnostic infrastructure experience.&lt;/p&gt;
&lt;h2 id="in-this-article"&gt;In This Article:&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#the-beginnings-of-sst"&gt;The Beginnings of SST&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#cdk-and-cloudformation-limitations"&gt;CDK and CloudFormation Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#a-provider-agnostic-solution-discovering-pulumi"&gt;A Provider-agnostic Solution: Discovering Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#transitioning-to-pulumi"&gt;Transitioning to Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#the-benefits-of-pulumi"&gt;The Benefits of Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/from-cdk-pulumi-evolution-of-sst/#the-future-of-sst-with-pulumi"&gt;The Future of SST with Pulumi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-beginnings-of-sst"&gt;The Beginnings of SST&lt;/h2&gt;
&lt;p&gt;Application developers have witnessed the rapid evolution of cloud computing and the growing need for developers to have direct access to powerful cloud resources. However, the traditional tools and approaches to Infrastructure as Code (IaC) have often been geared more toward DevOps teams, leaving application developers feeling disconnected from the infrastructure side of their projects.&lt;/p&gt;
&lt;p&gt;This was the driving force behind the creation of &lt;a href="https://sst.dev/"&gt;SST (Serverless Stack)&lt;/a&gt;, a framework that aims to bridge the gap between application developers and infrastructure management. In the early days, SST was built on top of AWS&amp;rsquo;s Cloud Development Kit (CDK), which allowed developers to define their infrastructure using TypeScript or Python. While this was a step in the right direction, they soon realized that the limitations of CDK and the underlying AWS CloudFormation were holding them back from truly empowering application developers.&lt;/p&gt;
&lt;h2 id="cdk-and-cloudformation-limitations"&gt;CDK and CloudFormation Limitations&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/LXxJ9XMXC6o?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;As the SST&amp;rsquo;s team continued to work with CDK and CloudFormation, they encountered several challenges that led them to reevaluate their approach. One key issue was the disconnect between application developers&amp;rsquo; thinking and working and traditional IaC tools&amp;rsquo; operating methods.&lt;/p&gt;
&lt;p&gt;With CDK and &lt;a href="https://www.pulumi.com/docs/iac/comparisons/cloudformation/#what-is-aws-cloudformation"&gt;CloudFormation&lt;/a&gt;, the infrastructure code is essentially a code generator, producing an intermediary format (such as YAML or JSON) that is then executed to deploy the resources. This means that the actual code you write as a developer is not the same as the code running during the deployment process. This can lead to several problems, such as difficulty debugging, lack of visibility into the deployment process, and challenges in extending or customizing the deployment workflow.&lt;/p&gt;
&lt;p&gt;Additionally, as the SST&amp;rsquo;s team expanded its focus beyond the AWS ecosystem and started exploring other cloud providers and even on-premises infrastructure, it found that the &lt;a href="https://www.pulumi.com/docs/iac/comparisons/aws-cdk/#what-is-aws-cdk"&gt;AWS-centric nature of CDK&lt;/a&gt; and CloudFormation was becoming a limitation. It needed a more flexible and provider-agnostic solution that would allow it to deploy and manage infrastructure across a wide range of platforms.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;AWS CDK&lt;/th&gt;
&lt;th&gt;Pulumi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-Cloud Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ AWS-Only&lt;/td&gt;
&lt;td&gt;✅ AWS, Azure, GCP, On-Prem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debugging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Hard due to CloudFormation&lt;/td&gt;
&lt;td&gt;✅ Real-time debugging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Language Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ TypeScript, Python&lt;/td&gt;
&lt;td&gt;✅ Any programming language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deployment Speed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Slower due to CloudFormation&lt;/td&gt;
&lt;td&gt;✅ Faster direct execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Visibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Hard to trace errors&lt;/td&gt;
&lt;td&gt;✅ Clear deployment state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extensibility&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚠️ Limited to AWS ecosystem&lt;/td&gt;
&lt;td&gt;✅ Custom providers &amp;amp; workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ CloudFormation state file&lt;/td&gt;
&lt;td&gt;✅ Pulumi-managed state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Secrets Management&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ AWS Secrets Manager only&lt;/td&gt;
&lt;td&gt;✅ Cross-cloud secret support&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="a-provider-agnostic-solution-discovering-pulumi"&gt;A Provider-agnostic Solution: Discovering Pulumi&lt;/h2&gt;
&lt;p&gt;It was during this time that the SST team discovered Pulumi, a modern IaC platform that takes a fundamentally different approach to infrastructure management. Instead of generating an intermediary format, Pulumi treats the infrastructure code as a first-class program executed directly during deployment.&lt;/p&gt;
&lt;p&gt;This paradigm shift had several important implications for SST and its users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Visibility and Extensibility&lt;/strong&gt;: With Pulumi, the infrastructure code is the same code that is running during deployment, which means there is much greater visibility into the deployment process and the ability to extend or customize it as needed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-Cloud Capabilities&lt;/strong&gt;: Pulumi&amp;rsquo;s provider-agnostic approach allows SST&amp;rsquo;s team to easily work with a wide range of cloud and on-premises platforms, giving their users the flexibility to deploy their infrastructure wherever it makes the most sense for their application.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplified Mental Model&lt;/strong&gt;: For application developers, the Pulumi model of &amp;ldquo;your code is the deployment&amp;rdquo; aligns much more closely with their existing mental models and workflows, making it easier for them to adopt and work with IaC tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="transitioning-to-pulumi"&gt;Transitioning to Pulumi&lt;/h2&gt;
&lt;p&gt;Transitioning SST from CDK to Pulumi was not a trivial undertaking. Still, they knew it was a necessary step to truly fulfill their mission of empowering application developers with powerful infrastructure management capabilities.&lt;/p&gt;
&lt;p&gt;One key challenge they faced was re-implementing the higher-level components and abstractions they had built on top of CDK. These components were designed to simplify the infrastructure management experience for their users, and they wanted to ensure that they could provide a similar level of abstraction and ease of use with Pulumi.&lt;/p&gt;
&lt;p&gt;Additionally, they had to carefully consider how to handle the various edge cases and complex deployment scenarios their users encountered with the CDK-based version of SST. They wanted to ensure that the Pulumi-based version would not only match the functionality of the previous version but also improve upon it and address some of the limitations they had encountered.&lt;/p&gt;
&lt;h2 id="the-benefits-of-pulumi"&gt;The Benefits of Pulumi&lt;/h2&gt;
&lt;p&gt;As they worked through the transition to Pulumi, they realized the significant benefits that Pulumi offered to both the SST team as the framework developers and the users.&lt;/p&gt;
&lt;p&gt;&lt;img src="sst-with-pulumi-infrastructure-as-code-deployments.png" alt="A quote from the Founding Engineer at SST: &amp;ldquo;With Pulumi, the deployment process feels like a natural extension of writing code - it&amp;rsquo;s intuitive and powerful and capable of advanced things that traditional IaC tools can&amp;rsquo;t handle.&amp;rdquo;"&gt;&lt;/p&gt;
&lt;h3 id="improved-visibility-and-debugging"&gt;Improved Visibility and Debugging&lt;/h3&gt;
&lt;p&gt;One of Pulumi&amp;rsquo;s most immediate and tangible benefits was the &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;improved visibility and debugging capabilities&lt;/a&gt; it provided. With the infrastructure code being the same as the deployment code, they could easily trace issues back to the source and understand exactly what was happening during the deployment process.&lt;/p&gt;
&lt;p&gt;This starkly contrasted the CDK/CloudFormation approach, where the intermediary format (CloudFormation templates) often obscured the underlying logic and made it much more difficult to diagnose and resolve problems.&lt;/p&gt;
&lt;h3 id="extensibility-and-customization"&gt;Extensibility and Customization&lt;/h3&gt;
&lt;p&gt;Pulumi&amp;rsquo;s design also allowed the SST team to easily extend and customize the deployment process to meet the specific needs of their users. They could leverage Pulumi&amp;rsquo;s built-in extensibility features, such as custom providers and dynamic components, to integrate with a wide range of cloud and on-premises services and implement complex deployment workflows tailored to our users&amp;rsquo; requirements.&lt;/p&gt;
&lt;p&gt;This level of customization was much more challenging with the CDK/CloudFormation approach, where they often had to resort to hacky workarounds or custom Lambda functions to achieve the desired functionality.&lt;/p&gt;
&lt;h3 id="multi-cloud-capabilities"&gt;Multi-Cloud Capabilities&lt;/h3&gt;
&lt;p&gt;As mentioned earlier, one key driver for their transition to Pulumi was the need to support a wider range of cloud and on-premises platforms. With Pulumi&amp;rsquo;s provider-agnostic approach, the SST team was able to easily add support for new providers, allowing their users to deploy and manage infrastructure across a diverse set of environments.&lt;/p&gt;
&lt;p&gt;This flexibility has been particularly valuable for their users, who may have workloads or requirements that span multiple cloud providers or even on-premises infrastructure. With SST built on Pulumi, they can now manage all of their infrastructure through a single, consistent interface without having to juggle multiple tools or approaches.&lt;/p&gt;
&lt;h3 id="simplified-mental-model"&gt;Simplified Mental Model&lt;/h3&gt;
&lt;p&gt;One of Pulumi&amp;rsquo;s most significant benefits for SST users is the simplified mental model it provides. By treating the infrastructure code as a first-class program, Pulumi aligns much more closely with how application developers think and work.&lt;/p&gt;
&lt;p&gt;Instead of having to navigate the complexities of intermediary formats, deployment pipelines, and the separation between infrastructure code and deployment code, SST users can now focus on writing their infrastructure logic in the same programming languages they use for their application code. This makes it much easier for them to understand, maintain, and extend their infrastructure as their needs evolve.&lt;/p&gt;
&lt;div class="rounded-lg bg-violet-50 p-6 my-8"&gt;
&lt;p class="heading-4 m-0 mb-3 flex items-center gap-1.5"&gt;Build across any cloud with Pulumi&lt;/p&gt;
&lt;div class="body-base m-0 text-gray-950"&gt;Define your infrastructure in TypeScript, Python, Go, or C#, and deploy it across AWS, Azure, Google Cloud, and on-premises environments from one consistent workflow.&lt;/div&gt;
&lt;a href="https://app.pulumi.com/signup" data-track="blog-body-cta" class="btn btn-primary mt-4"&gt;
Get started
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--regular size-4" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-arrow-right-regular"/&gt;&lt;/svg&gt;
&lt;/a&gt;
&lt;/div&gt;
&lt;h2 id="the-future-of-sst-with-pulumi"&gt;The Future of SST with Pulumi&lt;/h2&gt;
&lt;p&gt;With Pulumi&amp;rsquo;s foundation in place, they can now focus on further enhancing the developer experience and expanding the capabilities of their framework. Some of the key areas they are exploring include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Deeper Integration with Application Frameworks&lt;/strong&gt;: By leveraging Pulumi&amp;rsquo;s flexibility, they can create even tighter integrations between SST and the application frameworks and libraries that their users rely on, making managing infrastructure seamless alongside their application code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Expanded Provider Support&lt;/strong&gt;: the SST team will continue to add support for a wide range of cloud and on-premises providers, ensuring that their users can deploy and manage their infrastructure wherever it makes the most sense for their needs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Deployment Workflows&lt;/strong&gt;: Building on Pulumi&amp;rsquo;s extensibility, they can create &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/"&gt;more advanced deployment workflows&lt;/a&gt; that address the specific needs of application developers, such as faster deployment times, better rollback capabilities, and more granular control over the deployment process.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enhanced Observability and Monitoring&lt;/strong&gt;: By treating the infrastructure code as a first-class program, they can provide their users with &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;better visibility&lt;/a&gt; into the deployment process and more robust monitoring and observability capabilities, helping them to identify and resolve issues quickly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As the SST team continues to evolve with Pulumi at its core, they aim to deliver an even more powerful and user-friendly infrastructure management experience for developers. This will empower teams to focus on building great applications while effortlessly managing the underlying infrastructure.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;If you&amp;rsquo;re interested in exploring Pulumi further, here are several ways to get involved:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discover how Pulumi Crosswalk for AWS simplifies “day one” tasks in our &lt;a href="https://www.pulumi.com/docs/iac/clouds/aws/guides/"&gt;AWS guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Watch our on-demand workshop &lt;a href="https://www.pulumi.com/resources/getting-started-with-iac-pulumi-aws/"&gt;Getting Stated with Infrastructure as Code on AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Register for one of our upcoming &lt;a href="https://www.pulumi.com/resources/#upcoming"&gt;Platform Engineering or DevOps workshops&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;But most importantly, &lt;a href="https://app.pulumi.com/signup"&gt;try Pulumi&lt;/a&gt; today!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently Asked Questions&lt;/h2&gt;
&lt;h3 id="what-is-sst"&gt;What is SST?&lt;/h3&gt;
&lt;p&gt;SST is a framework that makes building modern full-stack applications on your infrastructure easy.&lt;/p&gt;
&lt;h3 id="what-is-ssts-ion"&gt;What is SST&amp;rsquo;s Ion?&lt;/h3&gt;
&lt;p&gt;Ion is the code name for a new engine for deploying SST applications. The constructs (or components) are deployed using Pulumi instead of CDK and CloudFormation (CFN). Once Ion is stable, it will be released as SST v3.&lt;/p&gt;
&lt;h3 id="does-sst-use-mostly-terraform-or-pulumi"&gt;Does SST use mostly Terraform or Pulumi?&lt;/h3&gt;
&lt;p&gt;SST leverages Pulumi behind the scenes for its providers and deployment engine while also bridging Terraform providers through Pulumi.&lt;/p&gt;
&lt;h3 id="how-does-sst-make-money"&gt;How does SST make money?&lt;/h3&gt;
&lt;p&gt;SST (Serverless Stack) makes money primarily through its managed service, called SST Console. The Console is optional and includes a free tier. In short, SST primarily relies on SaaS (Software as a Service) revenue through its managed platform and potentially supplemental income streams like enterprise services and consulting.&lt;/p&gt;</description><author>Sara Huddleston</author><category>cloudformation</category><category>aws-cdk</category><category>case-studies</category><category>developer-experience</category></item><item><title>Pulumi Patterns and Practices Platform (P3): A reference architecture for large-scale organizations</title><link>https://www.pulumi.com/blog/pulumi-patterns-and-practices/</link><pubDate>Mon, 05 Aug 2024 00:00:00 +0000</pubDate><guid>https://www.pulumi.com/blog/pulumi-patterns-and-practices/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/pulumi-patterns-and-practices/index.png" /&gt;
&lt;div class="note note-info"&gt;
&lt;div class="icon-and-line"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" class="ph-icon ph-icon--fill" fill="currentColor" aria-hidden="true" focusable="false"&gt;&lt;use href="https://www.pulumi.com/icons/sprite.fd29ca76b1ea49dbd3f6703cc46ae6138b0ed98cabf8d2c60a23a474880f964d.svg#p-info-fill"/&gt;&lt;/svg&gt;
&lt;div class="line"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class="content"&gt;Note: This post discusses Pulumi Copilot, which Pulumi Neo has replaced. &lt;a href="https://www.pulumi.com/docs/ai/"&gt;Learn about Neo →&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Infrastructure management is all fun and games until you find yourself scrolling through 1000+ resources in your AWS console. Worse, when one rogue product team wants to use Azure and your data team wants to be on GCP, you&amp;rsquo;re ARM wrestling in Azure and watching your economies of scale tip the wrong direction as you&amp;rsquo;re copy-pasting CloudFormation templates into yet another git repo. This. Needs. To. Be. A. Platform!&lt;/p&gt;
&lt;p&gt;And in that moment of overwhelm, you will be sold to, nurture-emailed every week, and told all your problems will be solved by implementing an IDP (internal developer platform, as if you&amp;rsquo;ve never seen this acronym before). An IDP that costs a lot of money and a lot of time to implement beyond default settings. An IDP that really only solves half of your problems. Your internal team offers to build something that feels more like welding together random pieces of code into an abstract found-art sculpture built from junkyard refuse, already 5 years out of date. How long will this investment be useful before you have to start over?&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s exhausting. If there was a good solution on the market, you wouldn&amp;rsquo;t be reading this article. So let&amp;rsquo;s talk about what you really need, and how Pulumi can help.&lt;/p&gt;
&lt;h2 id="an-effective-internal-developer-platform"&gt;An effective internal developer platform&lt;/h2&gt;
&lt;p&gt;There are quite a few &lt;a href="https://en.wikipedia.org/wiki/Listicle"&gt;listicles&lt;/a&gt; out there professing to authoritatively tell you the 5, or 7, or 11 essential components of an internal developer platform. Personally, I trust our customers to tell us, and here&amp;rsquo;s what they have said they need:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#consistency"&gt;Consistency:&lt;/a&gt;&lt;/strong&gt; Bring some order to the chaos. As your company and your infrastructure grows, it gets more and more complicated to maintain consistency. You might already have established design patterns that you want to replicate, but don&amp;rsquo;t have any way to encode those practices in your current tools. There&amp;rsquo;s a lot of copy/paste of reusable blocks, but no way to apply &lt;a href="https://www.youtube.com/watch?v=5xw04T20lto&amp;amp;t=7s"&gt;DRY principles&lt;/a&gt; or to modularize/templatize the important parts (hint: all the parts are important!).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#reproducibility"&gt;Reproducibility:&lt;/a&gt;&lt;/strong&gt; Repeatable behaviors, who dat? If you run your deploy twice do you get the same results each time? What if you replicate your production environment to create a test environment, are they actually identical? How much more work does it take to get them to be? Will you get the same version of the training dataset every time you run your AI workloads? It&amp;rsquo;s anyone&amp;rsquo;s guess. A lack of reproducibility slows down development, makes debugging more difficult, and makes that reuse we just talked about harder to achieve.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#visibility"&gt;Visibility:&lt;/a&gt;&lt;/strong&gt; When your node count, and user count starts to go beyond about 50-100 resources (computing or human) you quickly run into a problem of visibility. It can be very difficult to get a handle on what&amp;rsquo;s happening, how many resources you have, where they are, and how much they cost. Any system that purports to be able to manage 1000 nodes or more must have deeply integrated analytics, dashboards, charts, and be searchable, across all your clouds, all your users, and every kind of resource.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#security-and-compliance"&gt;Security and Compliance:&lt;/a&gt;&lt;/strong&gt; Good fences make good neighbors. RBAC, policy-as-code, excellent secrets management, integration with your existing identity providers. These are the things you need to build security and policy guardrails you can rely on. Without them? It&amp;rsquo;s just a powder keg of liability waiting to catch a spark.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#auditability"&gt;Auditability:&lt;/a&gt;&lt;/strong&gt; What happened and who did it? This is like a high-stakes game of &lt;a href="https://en.wikipedia.org/wiki/Cluedo"&gt;Clue&lt;/a&gt;. How quickly can you figure out who ran that bad deployment? Was it &lt;em&gt;Colonel Mustard&lt;/em&gt; in the &lt;em&gt;library&lt;/em&gt; with the &lt;em&gt;candlestick&lt;/em&gt;? Or Blake the new Front-End Developer with overly-broad permissions in AWS? Being able to answer these questions needs to happen quickly. Quickly, like minutes, not hours or days. And it might have happened 6 months ago. Oof.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.pulumi.com/blog/pulumi-patterns-and-practices/#auditability"&gt;Developer Experience:&lt;/a&gt;&lt;/strong&gt; In the ideal world, developers drive their own DevOps. The platform team provides self-service tools and streamlined workflows that allow your engineers to provision new resources, so your team doesn&amp;rsquo;t have to. And you know, if the developers don&amp;rsquo;t like the user experience, they won&amp;rsquo;t use it at all, and will invent their own tools. You will have ROGUE SYSTEMS to hunt down and argue against in tedious overly-technical meetings. This is not what you want. We need to keep the developers happy to prevent this.&lt;/p&gt;
&lt;h2 id="a-holistic-view-of-the-patterns-and-practices-platform-reference-architecture"&gt;A holistic view of the Patterns and Practices Platform reference architecture&lt;/h2&gt;
&lt;p&gt;Pulumi has a broad surface area of &lt;a href="https://www.pulumi.com/product/"&gt;products and features&lt;/a&gt; that address these needs. Designed with integration in mind from the beginning, our tools orchestrate well, presenting a smooth and streamlined workflow for both operations teams and developer teams.&lt;/p&gt;
&lt;p&gt;We have an idea of how you can use all the Pulumi products together to deliver a comprehensive internal platform for security, infrastructure management, and deployments. Call it an &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;internal platform for developer platform engineers&lt;/a&gt; (IPfDPE), if you want. We call it the realization of a vision we&amp;rsquo;ve been working hard to build for many years.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pulumi Patterns and Practices Platform (P3)&lt;/strong&gt; is a reference architecture that we will be describing, and providing code for, through this series of articles. We&amp;rsquo;ll be diving deep into not just what you can do with our tools, but how to do it, and provide code for a reference implementation that you can use to jump start the process.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick overview to give you an idea of how we&amp;rsquo;ll be addressing those needs in Pulumi Patterns and Practices Platform (P3).&lt;/p&gt;
&lt;h3 id="consistency"&gt;Consistency&lt;/h3&gt;
&lt;p&gt;Pulumi can help bring consistency to your software catalog by encoding design patterns into reusable &lt;em&gt;&lt;a href="https://www.pulumi.com/learn/abstraction-encapsulation/component-resources/"&gt;component resources&lt;/a&gt;&lt;/em&gt; and by building custom &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/developer-portals/templates/"&gt;organization templates&lt;/a&gt;&lt;/em&gt; that provide a no-code or low-code way to start a new project. Templates help get projects off the ground faster and ensure consistent code structure, policy compliance, and best practices.&lt;/p&gt;
&lt;figure&gt;
&lt;div class="my-4"&gt;
&lt;video class="flex outline-none rounded-lg w-full" title="The New Project Wizard in Pulumi Cloud"
autoplay muted playsinline
loop &gt;
&lt;source src="npw-720p.mp4" /&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;figcaption&gt;&lt;p&gt;Figure: An internal developer portal using custom templates in Pulumi Cloud&lt;/p&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Beyond that, because Pulumi is &lt;a href="https://www.pulumi.com/blog/deploy-to-multiple-regions/"&gt;multi-cloud&lt;/a&gt; (AWS, Azure, Google Cloud, and more) and &lt;a href="https://www.pulumi.com/blog/pulumiup-pulumi-packages-multi-language-components/"&gt;multi-language&lt;/a&gt; (JavaScript, Python, Go, C#, Java) you can enjoy the same consistency across all your environments and all your developer teams, regardless of the languages they prefer, or cloud tooling they need.&lt;/p&gt;
&lt;p&gt;Another core aspect of consistency is &lt;em&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/deployments/drift/"&gt;drift detection&lt;/a&gt;&lt;/em&gt;. Pulumi automatically detects and remediates cloud resources that have deviated from the expected state stored in Pulumi Cloud. This tech is better than ibuprofen at getting rid of developer-created headaches.&lt;/p&gt;
&lt;h3 id="reproducibility"&gt;Reproducibility&lt;/h3&gt;
&lt;p&gt;Since 2010, scientists have felt that we are in a crisis – a &lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Replication_crisis"&gt;reproducibility crisis&lt;/a&gt;&lt;/em&gt; – wherein we cannot easily reproduce an experiment in order to verify published results. Similarly, the software industry is entering into a reproducibility crisis of its own, especially around AI training workflows, where it is increasingly difficult to recreate crucial build and prod environments. &lt;a href="https://www.pulumi.com/learn/building-with-pulumi/understanding-stacks/"&gt;Pulumi Stacks&lt;/a&gt; make it very easy to manage both configuration and state across multiple environments, and make &lt;a href="https://www.pulumi.com/blog/simple-reproducible-kubernetes-deployments/"&gt;reproducing a deployment&lt;/a&gt; within Pulumi a matter of a few basic operations.&lt;/p&gt;
&lt;p&gt;You can use Pulumi programs to capture &lt;em&gt;&lt;strong&gt;all&lt;/strong&gt;&lt;/em&gt; of the necessary resources for an AI training workload, including things like versioned data using &lt;a href="https://www.pulumi.com/registry/packages/snowflake/api-docs/dynamictable/"&gt;dynamic tables&lt;/a&gt; with time-travel functionality in &lt;a href="https://www.pulumi.com/case-studies/snowflake/"&gt;Snowflake&lt;/a&gt;. That means you can be sure that not only will your deployment be on the infrastructure you need, it will also have the exact version of data, every time, which is essential to A/B testing and debugging your models.&lt;/p&gt;
&lt;h3 id="visibility"&gt;Visibility&lt;/h3&gt;
&lt;p&gt;Every resource under management by Pulumi is visible within &lt;a href="https://www.pulumi.com/product/pulumi-insights/"&gt;Pulumi Insights&lt;/a&gt;. From this single-pane-of-glass interface, you can search for resources across all cloud environments. &lt;a href="https://www.pulumi.com/product/copilot/"&gt;Pulumi Copilot&lt;/a&gt; provides a state-of-the-art AI chat interface to ask complex questions and get immediate results. Pulumi Insight&amp;rsquo;s analytics gives you the ability to identify anomalies or trends in resource usage and dig into cost, security, and compliance concerns.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/uploads/pulumi-insights-search.gif"
alt="Figure: Search for any resource with Pulumi Insights"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Search for any resource with Pulumi Insights&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="security-and-compliance"&gt;Security and Compliance&lt;/h3&gt;
&lt;p&gt;In the modern parlance, when you say DevOps, you mean DevSecOps. Pulumi is designed to be secure by default. Pulumi Cloud offers full &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/"&gt;role-based access control (RBAC) functionality&lt;/a&gt; including deep integration with &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/teams/#github-based-teams"&gt;GitHub teams&lt;/a&gt; and &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/access-management/saml/"&gt;SAML-based SSO&lt;/a&gt;, managed secrets and flexibly-defined secure environments with &lt;a href="https://www.pulumi.com/product/esc/"&gt;Pulumi ESC&lt;/a&gt;, and policy-as-code provided by &lt;a href="https://www.pulumi.com/crossguard/"&gt;Pulumi Crossguard&lt;/a&gt;. Most importantly all of these features are deeply integrated across the platform, creating an air-tight system with all the guardrails you need for managing security and access.&lt;/p&gt;
&lt;h3 id="auditability"&gt;Auditability&lt;/h3&gt;
&lt;p&gt;Every action a user takes in Pulumi can be tracked via the &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/"&gt;audit log&lt;/a&gt; which is searchable in two clicks from the Pulumi Cloud homepage dashboard. Audit logs can be filtered by user with one more click. Creating automated backups of your audit logs is a &lt;a href="https://www.pulumi.com/docs/pulumi-cloud/audit-logs/#automated-export"&gt;first-class feature&lt;/a&gt;. You will never have to worry about responding quickly when someone asks about an event that happened in your system. Also, each deployment and update has logs directly visible from the Pulumi Cloud app, regardless of how it was initiated.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/images/docs/guides/self-hosted/auditlogs.png"
alt="Figure: Viewing the audit log in Pulumi Cloud"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Viewing the audit log in Pulumi Cloud&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="developer-experience"&gt;Developer Experience&lt;/h3&gt;
&lt;p&gt;Probably the most compelling aspect of Pulumi is the developer experience. &lt;a href="https://www.pulumi.com/testimonials/"&gt;Developers love Pulumi&lt;/a&gt;, because they get to use their preferred tools. General purpose programming languages, visual IDEs, command-line tools, and products with an API-driven architecture are what developers want, and it&amp;rsquo;s what Pulumi delivers in spades.&lt;/p&gt;
&lt;p&gt;With Pulumi templates and custom internal component resources in place, &lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#how-does-devex-intersect-with-devops"&gt;developers can drive their own DevOps&lt;/a&gt;, provisioning their own infrastructure resources and managing their own deployments directly, reducing bottlenecks in platform teams. Product engineering teams can self-service with a stream-lined workflow that stays compliant with company policy by default. Deep in the code of their favorite programming languages, your developers will never even know they are following the company rules.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/pulumi-patterns-and-practices/pulumi-ide.png"
alt="Figure: Using C# to write a Pulumi program in VS Code"&gt;&lt;figcaption&gt;
&lt;p&gt;Figure: Using C# to write a Pulumi program in VS Code&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="more-to-come"&gt;More to Come&lt;/h3&gt;
&lt;p&gt;So now that we&amp;rsquo;ve made a case for how Pulumi can be applied to meet the most pressing needs of a larger organization, hopefully you will realize that the Pulumi Patterns and Practices Platform (P3) reference architecture we are presenting here is more than just infrastructure-as-code. P3 is a Pulumi-powered platform for teams, where your developer portal is not just a catalog of software, but a fully functional control-plane across all your cloud environments.&lt;/p&gt;
&lt;p&gt;Stay tuned for the following series of posts where we will use Pulumi to implement the P3 reference architecture for a fully-featured internal developer platform (IDP, or IPfDPE if you prefer). That said, you may already have invested in some popular in cloud-native tools like &lt;a href="https://www.pulumi.com/blog/pulumi-in-a-cloud-native-world/#the-kebap-stack-reference-architecture"&gt;Backstage&lt;/a&gt; or &lt;a href="https://www.pulumi.com/blog/kubernetes-4-0-even-more-kubernetes-native/"&gt;Kubernetes&lt;/a&gt;. Pulumi plays well with others, and you will be delighted to see &lt;a href="https://www.pulumi.com/blog/pulumi-in-a-cloud-native-world"&gt;how you can use Pulumi to cover the gaps&lt;/a&gt; in the &lt;a href="https://www.cncf.io/"&gt;CNCF&lt;/a&gt; ecosystem.&lt;/p&gt;
&lt;p&gt;And if you are already ready to get your hands on Pulumi after this introduction, feel free to &lt;a href="https://www.pulumi.com/signup/"&gt;create an account&lt;/a&gt; and follow some of our &lt;a href="https://www.pulumi.com/docs/get-started/"&gt;Getting Started&lt;/a&gt; guides to see how easy simple use cases are and begin to imagine how that same developer experience will scale up to your entire organization.&lt;/p&gt;
&lt;p&gt;To learn more, you can watch the following video which provides a high level overview of how Pulumi works:&lt;/p&gt;
&lt;div class="rounded-md shadow border border-gray-300 w-3/4 mx-auto my-4" style="position: relative; padding-bottom: 40.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe
src="//www.youtube.com/embed/Q8tw6YTD3ac?rel=0"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;"
allowfullscreen=""
title="Introduction to Pulumi in Three Minutes"
srcdoc="&lt;style&gt;*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img{position:absolute;width:100%;top:0;bottom:0;margin:auto}&lt;/style&gt;&lt;a href=https://www.youtube.com/embed/Q8tw6YTD3ac?autoplay=1&gt;&lt;img src='https://www.pulumi.com/images/home/youtube-getting-started.png' alt='Introduction to Pulumi in Three Minutes'&gt;&lt;/a&gt;"&gt;
&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="pulumi-cloud"&gt;Pulumi Cloud&lt;/h2&gt;
&lt;p&gt;The Pulumi Cloud is a fully managed service that helps you adopt Pulumi&amp;rsquo;s open source SDK with ease. It provides built-in state and secrets management, integrates with source control and CI/CD, and offers a web console and API that make it easier to visualize and manage infrastructure. It is free for individual use, with features available for teams.&lt;/p&gt;
&lt;p&gt;&lt;a class="btn btn-secondary" href="https://app.pulumi.com/signup" target="_blank"&gt;Create an Account&lt;/a&gt;&lt;/p&gt;</description><author>Troy Howard</author><category>platform-engineering</category><category>patterns-and-practices-platform</category><category>developer-experience</category><category>devsecops</category><category>architecture</category><category>enterprise</category><category>devops</category></item><item><title>Platform Engineering &amp; DevOps Series Kickoff Announcement</title><link>https://www.pulumi.com/blog/platform-engineering-devops-event-meetup-community/</link><pubDate>Mon, 15 Jul 2024 14:38:46 +0000</pubDate><guid>https://www.pulumi.com/blog/platform-engineering-devops-event-meetup-community/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/platform-engineering-devops-event-meetup-community/index.png" /&gt;
&lt;p&gt;We are excited to announce the kickoff of the Platform Engineering &amp;amp; DevOps Series, which will run from July 16 to October 31. This series will feature in-person events across various cities, including Berlin, London, Paris, Sydney, Boston, San Francisco, Seattle, Austin, Denver, and NYC. For those unable to attend an in-person event, we encourage you to participate in a virtual DevOps &amp;amp; Platform Engineering workshop.&lt;/p&gt;
&lt;h2 id="upcoming-in-person-events"&gt;Upcoming In-Person Events&lt;/h2&gt;
&lt;p&gt;Pulumi is hosting in-person meetups and virtual workshops for engineers interested in Platform Engineering and DevOps, covering topics from best practices to setup and implementation to advanced topics. Join us for tech talks, hands-on workshops, and opportunities to network with fellow engineers.&lt;/p&gt;
&lt;h3 id="first-platform-engineering--devops-in-person-event-berlin---july-16"&gt;First Platform Engineering &amp;amp; DevOps in-person event: Berlin - July 16&lt;/h3&gt;
&lt;p&gt;Join &lt;a href="https://www.linkedin.com/in/dominik-kress-33a540174/"&gt;Dominik Kress&lt;/a&gt; (Product Manager at Giant Swarm and member of the CNCF Platforms Working Group) and &lt;a href="https://www.linkedin.com/in/guy-menahem/"&gt;Guy Menahem&lt;/a&gt; (Solutions Architect at Komodor and community leader at The Platformers) at LOBE Block for an engaging discussion on platform engineering.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dominik Kress will present &amp;ldquo;What the Heck is the CNCF Platform Working Group? Answers from a Member!&amp;rdquo;&lt;/li&gt;
&lt;li&gt;Guy Menahem will present &amp;ldquo;For This Backstage, You Don’t Need a Special Pass: Platform Engineering in Practice.&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more details and to RSVP, visit the &lt;a href="https://luma.com/pulumi"&gt;Berlin Meetup page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="second-in-person-event-boston-july-24"&gt;Second In-Person Event: Boston, July 24&lt;/h3&gt;
&lt;p&gt;Join Pulumi&amp;rsquo;s founder &amp;amp; CEO, &lt;a href="https://www.linkedin.com/in/joejduffy/"&gt;Joe Duffy&lt;/a&gt;, and &lt;a href="https://www.linkedin.com/in/jbaldanza/"&gt;Jamie Baldanza&lt;/a&gt;, Director of DevOps at Relay Therapeutics, for the launch of our Boston meetup at The Foundry. This is a great opportunity for DevOps engineers, platform engineers, software engineers, and Cloud enthusiasts to connect and share insights.&lt;/p&gt;
&lt;p&gt;RSVP is required due to limited capacity. Secure your spot, and RSVP at the &lt;a href="https://luma.com/pulumi"&gt;Boston Meetup page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="more-coming-soon"&gt;More coming soon!&lt;/h3&gt;
&lt;p&gt;We expected Seattle, Paris, and London&amp;rsquo;s meetups to happen in early September.
Details for the other in-person events will be coming soon, so stay tuned for more updates at &lt;a href="https://info.pulumi.com/platform-engineering-devops-series"&gt;Platform Engineering &amp;amp; DevOps Series&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;No upcoming in-person events in your area? Attend one of our virtual workshops and keep up with the latest in DevOps &amp;amp; Platform Engineering!&lt;/p&gt;
&lt;h3 id="virtual-workshops"&gt;Virtual Workshops&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Getting Started with CI/CD for AWS using GitHub Actions&lt;/strong&gt;: July 17. Learn more and &lt;a href="https://www.pulumi.com/resources/getting-started-with-ci-cd-aws-pulumi-github-actions/"&gt;register here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;From Zero to Production in Kubernetes&lt;/strong&gt;: July 25. Learn more and &lt;a href="https://www.pulumi.com/resources/from-zero-to-production-in-kubernetes/"&gt;register here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Advanced CI/CD for AWS using Pulumi and GitHub Actions&lt;/strong&gt;: August 14. Learn more and &lt;a href="https://www.pulumi.com/resources/advanced-cicd-aws-pulumi-github-actions/"&gt;register here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mastering Platform Engineering: From Setup to Scaling Success&lt;/strong&gt;: TBD.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Join us for tech talks, hands-on workshops, and opportunities to network with industry peers. We are excited to meet you in person or virtually.
See you there!&lt;/p&gt;</description><author>Sara Huddleston</author><category>developer-experience</category><category>devops</category><category>platform-engineering</category><category>community</category><category>pulumi-events</category></item><item><title>Why Developer Experience (DevEx) is Business Critical</title><link>https://www.pulumi.com/blog/developer-experience-business-critical/</link><pubDate>Tue, 20 Feb 2024 20:47:44 +0000</pubDate><guid>https://www.pulumi.com/blog/developer-experience-business-critical/</guid><description>
&lt;img src="https://www.pulumi.com/images/generated/blog/developer-experience-business-critical/index.png" /&gt;
&lt;p&gt;&amp;ldquo;Developer experience is hard to sell,&amp;rdquo; said Cleve Littlefield, Engineering Manager at Pulumi, during a casual meeting. With experience as both an end-user developer and a lead in self-service platform implementation, Cleve&amp;rsquo;s observation stuck with me.&lt;/p&gt;
&lt;p&gt;Though I have expertise in leading implementations and upgrades for internal platforms, none were specifically for developers. However, experience remains vital across departments, addressing tools, processes, systems, and best practices, aiming to reduce cognitive load, increase productivity, enhance collaboration, boost communication and much more.&lt;/p&gt;
&lt;p&gt;Intriguingly, engineering teams may perceive its value differently. Therefore, we will dive into the concept of developer experience, aka DevEx, which, in truth, should translate into a competitive advantage.&lt;/p&gt;
&lt;h2 id="in-this-devex-article"&gt;In this DevEx article&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#what-is-developer=experience"&gt;What is developer experience?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#is-developer-experience-important"&gt;Is developer experience important?&lt;/a&gt; (Spoiler alert: it&amp;rsquo;s business-critical)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#the-github-developer-experience-devex-formula"&gt;The GitHub developer experience (DevEx) formula&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#what-does-a-great-developer-experience-look-like"&gt;What does a great developer experience look like?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#how-does-devex-intersect-with-devops"&gt;How does DevEx intersect with DevOps?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#organizational-culture-is-a-predictor-of-outcome-success"&gt;Organizational culture is a predictor of outcome success&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#how-do-you-implement-a-great-developer-experience"&gt;How do you implement a great developer experience?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#what-devex-is-not"&gt;What DevEx is not&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/software-developer-experience-devex-devx-devops-culture/#frequently-asked-questions"&gt;Frequently asked questions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-is-developer-experience"&gt;What is developer experience?&lt;/h2&gt;
&lt;p&gt;Developer experience (DevEx), also referred to as DevX or DX, encompasses systems, technology, processes, and culture that collectively impact the effectiveness of software development. It looks at all components of a developer&amp;rsquo;s ecosystem—from environment to workflows to tools—and evaluates how they contribute to developer productivity, satisfaction, and operational impact.&lt;/p&gt;
&lt;p&gt;Developer experience revolves around the ease or difficulty of executing essential tasks. &lt;strong&gt;A positive developer experience means those tasks are relatively easy to perform, translating into higher performance.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The quality of the experience is equally vital for developers building and managing internal software as it is for those involved in developing customer-facing software products.&lt;/p&gt;
&lt;h2 id="is-developer-experience-important"&gt;Is developer experience important?&lt;/h2&gt;
&lt;p&gt;It is not just important. &lt;strong&gt;It&amp;rsquo;s business critical.&lt;/strong&gt; If your company is in the business of creating and selling software or relies on critical internal software, developers are vital internal stakeholders to your business foundation.&lt;/p&gt;
&lt;p&gt;Greg Mondello, director of product at GitHub, said, &amp;ldquo;In most contexts, software development capacity is the limiting factor for innovation. Therefore, improvements to the effectiveness of software development are inherently valuable [&amp;hellip;] companies with better DevEx outperform their competitors, regardless of vertical.&amp;rdquo;&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/what-impact-are-you-experiencing-resulting-of-improving-developer-experience.jpg"
alt="Platform Engineering Forrester Opportunity Snapshot - DevEx impacts overall business performance. Credit: Humanitec" width="70%"&gt;&lt;figcaption&gt;
&lt;p&gt;Platform Engineering Forrester Opportunity Snapshot - DevEx impacts overall business performance. Credit: Humanitec&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;As per &lt;a href="https://www.mckinsey.com/capabilities/mckinsey-digital/our-insights/tech-forward/why-your-it-organization-should-prioritize-developer-experience"&gt;McKinsey&amp;rsquo;s report&lt;/a&gt;, an enhanced developer experience (DevEx) can yield significant advantages for organizations, including enhanced talent hiring and retention, improved security, and increased developer productivity- this makes DevEx important for all companies, not just tech.&lt;/p&gt;
&lt;p&gt;A positive developer experience can yield numerous business advantages, which can include:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Improvement in collaboration across departments&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Higher attraction and retention top talent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increase developer productivity and developer velocity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduction in operational costs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Accelerate time-to-market&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support innovation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elevate customer attraction and retention&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Increase bottom line through revenue growth&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To this end, let&amp;rsquo;s look into what goes into developer experience and how to achieve it.&lt;/p&gt;
&lt;h2 id="the-github-developer-experience-devex-formula"&gt;The GitHub developer experience (DevEx) formula&lt;/h2&gt;
&lt;p&gt;GitHub&amp;rsquo;s DevEx formula takes into consideration the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Productivity: The speed and simplicity of implementing changes to a codebase&lt;/li&gt;
&lt;li&gt;Impact: The seamless transition from idea to production without obstacles&lt;/li&gt;
&lt;li&gt;Satisfaction: The environment, workflows, and tools influence developer happiness&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Optimizing DevEx involves fostering a collaborative environment where developers can be most productive, impactful, and satisfied.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/github-developer-experience-formula.png"
alt="DevEx formula. Credit: GitHub" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;DevEx formula. Credit: GitHub&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Noah Gift, the founder of Pragmatic AI Labs and a professor at Duke University specializing in machine learning, MLOps, AI, data science, and cloud architecture, noted that with the right platform, there could be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A 75% increase in productivity&lt;/li&gt;
&lt;li&gt;A sustained 22% productivity increase three years later&lt;/li&gt;
&lt;li&gt;An 80% reduction in onboarding time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Merely having skilled developers is insufficient. Developers also require the appropriate tools and processes to excel in their work. Top-tier developers anticipate the availability of such resources, influencing the hiring and retention of talent.&lt;/p&gt;
&lt;h2 id="what-does-a-great-developer-experience-look-like"&gt;What does a great developer experience look like?&lt;/h2&gt;
&lt;p&gt;Engineering teams that have good developer experiences are more productive and efficient. Great DevEx is often enabled by a platform where the end-users are the developers.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developer-first readily available &lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-3/"&gt;internal developer platform&lt;/a&gt;, infrastructure, and development tooling, with well-organized and explicit documentation, including tutorials, demo environments, and curated learning paths.&lt;/li&gt;
&lt;li&gt;A unified hub for all developer requirements eliminates the need for developers to navigate through numerous tools, saving valuable time.&lt;/li&gt;
&lt;li&gt;Simplified workflows emerge when developers can swiftly select app patterns, such as API microservices or front-end journeys, and deploy them within minutes. This includes all-encompassing elements like environments, pre-integrated DevSecOps pipelines, monitoring, and fully automated change and release procedures.&lt;/li&gt;
&lt;li&gt;Centralized tracking of software, API, and infrastructure status and versions promotes asset transparency. A real-time view supports adherence to architectural standards, security controls, and patching status, with bots offering automatic suggestions for code enhancements related to issues.&lt;/li&gt;
&lt;li&gt;Integrated analytics and KPIs such as developer velocity, tech debt, error rate, mean time to recovery, and infrastructure cost can be automatically pulled by standard organizational tools, including backlog, pipeline, and monitoring tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/github-study-what-developers-spend-themost-time-on-daily.png"
alt="Survey by GitHub on a typical experience for developers. Credit: GitHub" width="60%"&gt;&lt;figcaption&gt;
&lt;p&gt;Survey by GitHub on a typical experience for developers. Credit: GitHub&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Without the proper tools, progress may slow down the development process and hinder developer productivity. It becomes crucial to implement appropriate measures to avoid disruptions that could impact everyone involved, including the developers themselves. Although not often mentioned, &lt;a href="https://www.pulumi.com/what-is/what-is-devops/"&gt;DevOps&lt;/a&gt; and &lt;a href="https://www.pulumi.com/what-is/what-is-platform-engineering/"&gt;Platform Engineering&lt;/a&gt; also aim to enhance the developer experience and achieve the associated benefits.&lt;/p&gt;
&lt;h2 id="how-does-devex-intersect-with-devops"&gt;How does DevEx intersect with DevOps?&lt;/h2&gt;
&lt;p&gt;DevOps is about developers and operations working together and sharing values, assumptions, and responsibility for the software they build and maintain.&lt;/p&gt;
&lt;p&gt;According to Vilas Veeraraghavan, VP of Engineering at Truckstop, &amp;ldquo;Developer Experience (DevEx) is the investment you make to enable solid DevOps practices, reduce developer burnout, and improve retention. The need for this investment is more pronounced as companies grow and the tech stack gets more diverse.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Watch Jowanza Joseph, Head of Engineering at StreamFT, below as he discusses how the right tool empowered developers, improved DevEx, reduced bottlenecks, increased productivity, and helped DevOps be a culture, a practice, not a person.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/I-GQ1xpyV0E?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;p&gt;Let&amp;rsquo;s address a strong indicator of success or failure - culture.&lt;/p&gt;
&lt;p&gt;Culture is not something you are—it&amp;rsquo;s something you do. Software companies often focus on DevOps practices and culture, but all would benefit from adopting a DevOpsAll since the entire company should strive for the same thing. The diversity of perspectives, ideas, and insights can spark creativity and innovation and even ensure product-market alignment.&lt;/p&gt;
&lt;h2 id="organizational-culture-is-a-predictor-of-outcome-success"&gt;Organizational culture is a predictor of outcome success&lt;/h2&gt;
&lt;p&gt;Why it matters? Organizational culture encompasses everyone, from the development team and operations to product management teams, sales, marketing, and more.&lt;/p&gt;
&lt;p&gt;According to George Spafford, Senior Director Analyst at Gartner, &amp;ldquo;Infrastructure &amp;amp; Operations leaders embarking on DevOps initiatives and struggling to address organizational change and the value they will provide to the larger enterprise [&amp;hellip;] people-related factors tend to be the greatest challenges — not technology.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;According to a Harvard study encompassing 200 companies over 11 years, companies that focused on shaping their culture outperformed their competitors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Revenue growth was 4.1 times higher&lt;/li&gt;
&lt;li&gt;The stock price was 12.2 times higher&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.investopedia.com/terms/n/netincome.asp"&gt;Net income&lt;/a&gt; was 756% vs. 1%&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.investopedia.com/terms/r/returnoninvestment.asp"&gt;Return on investment (ROI)&lt;/a&gt; was 15 times higher&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The driving force behind this exceptional financial performance is that engaged employees are prone to increased productivity, fostering superior innovation and more effective problem-solving.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/employee-developer-experience-focus-areas.jpeg"
alt="Slide from a New York Atlassian Community Group presentation. Credit: Mark Cruth, principal modern work coach / advocate at Atlassian" width="80%"&gt;&lt;figcaption&gt;
&lt;p&gt;Slide from Mark&amp;rsquo;s New York Atlassian Community Group presentation. Credit: Mark Cruth, principal modern work coach/advocate at Atlassian&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Based on decades of research on employee engagement, &lt;a href="https://www.gallup.com/workplace/285674/improve-employee-engagement-workplace.aspx#ite-357638"&gt;Gallup has established that engaged employees consistently yield superior business outcomes compared to their counterparts&lt;/a&gt;. This holds true across various industries, company sizes, and nationalities and remains consistent in prosperous and challenging economic conditions.&lt;/p&gt;
&lt;p&gt;If it is not yet clear, then I will spell it out. Developer experience impacts employee engagement. A better developer experience can boost the engagement of the engineers and developers in the organization, and more engaged people are more likely to go the extra mile.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/developer-experience-more-engaged-developers.png"
alt="How developer experience supports better business outcomes. Credit: Swarmia" width="100%"&gt;&lt;figcaption&gt;
&lt;p&gt;How developer experience supports better business outcomes. Credit: Swarmia&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;If organizations invest in cultural values centered on human-first factors, then even the choices made in tools, processes, and systems will also be with the end-user in mind.&lt;/p&gt;
&lt;h2 id="how-do-you-implement-a-great-developer-experience"&gt;How do you implement a great developer experience?&lt;/h2&gt;
&lt;p&gt;There isn&amp;rsquo;t a bulletproof checklist, but there are several aspects to consider, and you can see the outline below. First, you need to view the developers as customers.&lt;/p&gt;
&lt;p&gt;You will need to understand how developers work, the developer workflow, what the onboarding process looks like for a new developer, the developer teams&amp;rsquo; pain points, what developers love and hate about their day-to-day work, where they are spending most of their time, where they wish they spent most of their time, and so much more, that boils down to communication, and asking the right questions, and deep diving into analytics.&lt;/p&gt;
&lt;h3 id="cultivate-a-devops-culture"&gt;Cultivate a DevOps culture&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Shared responsibility&lt;/strong&gt;: Encourage a culture of shared responsibility where developers, operations, and other stakeholders work collaboratively&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Continuous learning&lt;/strong&gt;: Promote a culture of continuous learning and improvement to adapt to evolving technologies and methodologies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Open communication&lt;/strong&gt;: Foster open communication channels to enhance collaboration and transparency among team members&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Company-wide collaboration tools&lt;/strong&gt;: It&amp;rsquo;s essential to encourage communication among developers and cross-functional teams to stimulate creativity, spark innovation, and enhance productivity and the speed of decision-making. Cross-functional collaboration contributes to successful business outcomes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="define-clear-objectives"&gt;Define clear objectives&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Alignment with business goals&lt;/strong&gt;: Ensure DevEx objectives align with business goals to drive meaningful outcomes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User-centric approach&lt;/strong&gt;: Prioritize user needs and feedback, shaping the DevEx strategy around the actual experiences of developers&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="leverage-developer-first-tools"&gt;Leverage developer-first tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/blog/building-developer-portals/"&gt;&lt;strong&gt;Internal developer portals (IDPs)&lt;/strong&gt;&lt;/a&gt;: IDPs enable developers to quickly provision approved infrastructure, boosting productivity with pre-configured architectures, automated testing, and deployment adhering to organizational standards&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI pipelines&lt;/strong&gt;: usually, pipelines can be made faster and more unified. If they have a microservice architecture, they are likely duplicating pipeline code for every service&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/languages-sdks/"&gt;&lt;strong&gt;Software development kits (SDKs)&lt;/strong&gt;&lt;/a&gt;: SDKs are integral components of a positive DevEx and provide developers with tools that facilitate crafting applications tailored to specific platforms or frameworks. Offering easy-to-access, well-designed, functional SDKs can make a meaningful difference in helping engineers quickly prototype ideas and refine their creations&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pulumi.com/docs/pulumi-cloud/"&gt;&lt;strong&gt;Infrastructure as code (IaC)&lt;/strong&gt;&lt;/a&gt;: Developers like to write code, particularly in their preferred programming language, provision infrastructure, ensuring consistency and reproducibility&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitoring and observability&lt;/strong&gt;: Implement effective monitoring and observability tools (e.g., Prometheus, &lt;a href="https://www.pulumi.com/resources/observability-as-code-with-new-relic/"&gt;New Relic&lt;/a&gt;, Grafana) to gain insights into application performance and proactively address issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Collaborative documentation platforms&lt;/strong&gt;: Use collaborative documentation platforms to document code, processes, and best practices, ensuring knowledge sharing and reducing onboarding friction&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://www.pulumi.com/blog/developer-experience-business-critical/steps-to-improve-developer-experience.jpg"
alt="Platform Engineering Forrester Opportunity Snapshot - which of the following steps has your org take to improve the developer experience? Top 43% internal developer platform or platform engineering Credit: Humanitec" width="70%"&gt;&lt;figcaption&gt;
&lt;p&gt;Platform Engineering Forrester Opportunity Snapshot - Which of the following steps organizations are taking to improve DevEx? Credit: Humanitec&lt;/p&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="prioritize-developer-friendly-workflows"&gt;Prioritize developer-friendly workflows&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fast feedback loops&lt;/strong&gt;: Minimize feedback loops by integrating quick feedback mechanisms, allowing developers to identify and resolve issues early in the development cycle&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-service environments&lt;/strong&gt;: Provide developers with self-service environments to facilitate experimentation, testing, and debugging without unnecessary dependencies on other teams&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Version control best practices&lt;/strong&gt;: Enforce version control best practices to maintain a clean and organized codebase, allowing for easier collaboration and tracking of changes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="continuous-integration-of-feedback"&gt;Continuous integration of feedback&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Developer surveys&lt;/strong&gt;: Conduct regular surveys to gather feedback on the DevEx, ensuring continuous improvement based on real user experiences&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rapid iteration&lt;/strong&gt;: Encourage a culture of rapid iteration, where feedback is quickly incorporated into the development process to enhance the overall developer experience&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="measure-and-optimize"&gt;Measure and optimize&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Key performance indicators (KPIs)&lt;/strong&gt;: Define and track key metrics such as deployment frequency, lead time, and mean time to recovery to measure the effectiveness of the DevEx strategy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Iterative optimization&lt;/strong&gt;: Continuously iterate and optimize DevEx based on performance metrics and user feedback&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.pulumi.com/blog/platform-engineering-pillars-4/"&gt;Implementing a Developer Experience&lt;/a&gt; requires a holistic approach that blends cultural aspects with powerful DevOps and platform engineering tools. Watch Daniel Tao, Head of Engineering at &lt;a href="https://www.pulumi.com/case-studies/atlassian/"&gt;Atlassian&lt;/a&gt;, and Sven Peters, developer evangelist, discuss how to build a great developer experience through culture and an integrated approach to developer tools.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/xriRD7ugX20?si=LurTGLx1KfgRGIQZ&amp;amp;t=192?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h2 id="what-devex-is-not"&gt;What DevEx is not&lt;/h2&gt;
&lt;p&gt;Now that DevEx has been defined, let&amp;rsquo;s address some common misconceptions about developer experience.&lt;/p&gt;
&lt;h3 id="devex-is-not-the-same-as-user-experience-ux"&gt;DevEx is not the same as User Experience (UX)&lt;/h3&gt;
&lt;p&gt;Developer experience may sound similar to user experience (for developers), but it&amp;rsquo;s different, although user experience is a component. For example, a platform engineer &lt;a href="https://www.pulumi.com/blog/developer-portal-platform-teams/"&gt;building an internal developer platform&lt;/a&gt; must view the developers as their customers and create a good user experience by making it intuitive and easy to use.&lt;/p&gt;
&lt;h3 id="devex-is-not-about-enabling-lazy-developers"&gt;DevEx is not about enabling lazy developers&lt;/h3&gt;
&lt;p&gt;Part of the DevEx strategy is to retain talent. Companies that invest in DevEx don&amp;rsquo;t do it to pamper developers. The true reason behind it is that they want their developers to stay &amp;ldquo;in the zone,&amp;rdquo; also known as &amp;ldquo;deep work.&amp;rdquo; When in this state, they are immersed in writing code and solving problems they enjoy working on, and their creativity is higher, it sparks innovative ideas, and the quality and speed of their output are also higher.&lt;/p&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
&lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/NbhpII8DIKA?rel=0?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;h3 id="devex-is-not-about-implementing-ai-and-cool-tools"&gt;DevEx is not about implementing AI and cool tools&lt;/h3&gt;
&lt;p&gt;Technology impacts developer experience, &lt;a href="https://www.pulumi.com/product/neo/"&gt;a robust generative AI tool can help create code faster&lt;/a&gt;, and internal developer platforms can help reduce cognitive load on developers. But again, tooling is only one aspect of it. Tools can&amp;rsquo;t fix culture or replace processes. Many DevEx considerations should be considered to ensure that when the development teams adopt a tool, it addresses their pain points and enables developers.&lt;/p&gt;
&lt;h3 id="devex-is-not-a-one-person-decision"&gt;DevEx is not a one-person decision&lt;/h3&gt;
&lt;p&gt;DevEx should be a joint effort from the entire team. One needs to be aware of the issues to plan to fix them, so open communication and team collaboration are vital to developing and implementing a DevEx strategy, intersecting DevOps and platform engineering initiatives. Many large organizations already have DevEx teams or professionals with a bird&amp;rsquo;s-eye view of what happens within the engineering team. They are internal advocates for software engineers. They consider the developer&amp;rsquo;s journey from being new developers and their &amp;lsquo;Time to First Contribution&amp;rsquo; to day-to-day activities. They work with engineers to learn which problems are a priority and identify misconceptions and bottlenecks that may slow the development process.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Developer experience (DevEx) is essential for creating maximum output while increasing developer satisfaction. The appropriate technology tools, workflows, and a supportive development community can help foster progress and innovation while promoting high-quality software engineering results that can become a competitive advantage and ultimately benefit the business&amp;rsquo;s bottom line.&lt;/p&gt;
&lt;p&gt;By dedicating attention to improving the DevEx, companies will also be able to bring more talent aboard, reduce their &amp;ldquo;Time to First Contribution,&amp;rdquo; enable developers to provide higher output contributions and improve talent retention. It&amp;rsquo;s time to start focusing on superior developer experiences.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Discover &lt;a href="https://www.pulumi.com/blog/developer-portal-platform-teams/"&gt;Pulumi for Platform Teams: New Features for Developer Portals, Policy and Deployments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Read &lt;a href="https://www.pulumi.com/blog/pulumi-developer-workflow/"&gt;The Pulumi &amp;lsquo;Push to start&amp;rsquo; GitOps Experience&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id="frequently-asked-questions"&gt;Frequently asked questions&lt;/h2&gt;
&lt;h3 id="what-does-business-critical-mean"&gt;What does business critical mean?&lt;/h3&gt;
&lt;p&gt;Business critical means essential for a business to operate and be successful. It refers to business processes, systems, or activities that are considered essential for proper functioning, success, or survival. If these elements are disrupted or compromised, the impact can significantly affect its operations, financial health, or overall business objectives. Business-critical components are often prioritized for attention, protection, and resource allocation to ensure the organization&amp;rsquo;s continued effectiveness and stability, and to remain competitive.&lt;/p&gt;
&lt;h3 id="what-is-the-role-of-a-developer-experience-engineer-dxe"&gt;What is the role of a Developer Experience Engineer (DXE)?&lt;/h3&gt;
&lt;p&gt;Developer Experience Engineers are internal advocates indispensable to making life easier for developers by making workflows more efficient, implementing the same processes across the development team, and assisting in choosing tools to lighten their load. Some companies do not necessarily have engineers with that job title, and it&amp;rsquo;s instead seen as part of DevOps or Platform Engineering initiatives. Other times, the internal developer advocate natural rises from the developer community to help form an integral part of the developer team&amp;rsquo;s unity. They also champion communication and work with cross-function coworkers and feel safe means of providing constructive feedback.&lt;/p&gt;
&lt;h3 id="how-do-we-cultivate-a-positive-developer-community"&gt;How do we cultivate a positive developer community?&lt;/h3&gt;
&lt;p&gt;The importance of DevEx&amp;rsquo;s human element is now in focus. A productive and effective developer community could be seen as a flourishing habitat, strengthening cooperation and maximizing productivity through collaboration. Such an atmosphere also sustains morale among the developers, resulting in job satisfaction and contentment.&lt;/p&gt;
&lt;p&gt;Here are some steps to build a developer community: open communication needs to become standard, successes should consistently be recognized, and avenues for growth need to exist. Diversity and acceptance are significant. Task expectations should be attainable goals and set high enough not to compromise quality but not realistic so they can be achieved without burnout and unbalanced life routines.&lt;/p&gt;
&lt;h3 id="how-does-technology-impact-developer-experience"&gt;How does technology impact developer experience?&lt;/h3&gt;
&lt;p&gt;Technological advancements continue to change software development and impact the Developer experience. AI, ML, TDD, and internal developer platforms are some of these technologies that help reduce developers&amp;rsquo; cognitive load. They automate complex tasks for more accuracy and enable intelligent decision-making. Besides this, generative AI has come into play in creating higher-quality code faster. At the same time, GitOps is a management approach based on one source of truth - Git, which makes collaboration smoother &amp;amp; boosts productivity by allowing automation. All these things undoubtedly improve the DX substantially for any developer out there!&lt;/p&gt;</description><author>Sara Huddleston</author><category>developer-experience</category><category>devops</category><category>platform-engineering</category><category>developer-portals</category><category>software-development</category></item></channel></rss>