Hi :wave: I'm currently designing an internal deve...
# getting-started
p
Hi 👋 I'm currently designing an internal developer platform (IDP) using Pulumi OSS + Automation API, and I'd really appreciate some validation or correction from people who've built or operated Pulumi-based platforms at scale. I want to explain my thinking clearly, because I'm not sure whether we're converging on the right model—or over-engineering something unnecessarily. Question: Is it really the right direction for an IDP to generate Pulumi programs?
Why we use Pulumi (important context) We don't use Pulumi just to write infrastructure configuration in a programming language. The primary reason is: > To control infrastructure lifecycle and execution flow programmatically via Automation API. Not because TypeScript is inherently better than YAML for describing infrastructure settings. What IaC should guarantee (in our view) Regardless of tool choice, IaC should ensure: • *Infrastructure configuration always leaves artifacts*Code + state remain for inspection, recovery, and audit • *The same infrastructure code must be operable via:*CLI (for import, migration, emergency fixes) • API / Automation (CI, IDP) • Common infrastructure patterns should be reusable and modular • Git should remain the source of truth Where the dilemma starts From this perspective: • *Infrastructure configuration itself does not necessarily need to be written in a programming language*YAML could be simpler and more readable However, writing infrastructure definitions in a programming language does have advantages: • Conditionals, branching, and complex logic can be expressed naturally • YAML quickly hits limits when these are needed This leads to a tension: > If Pulumi is mainly used for execution and orchestration via Automation API, do infrastructure definitions really need to be written in a programming language? At first, YAML seems sufficient. But realistically: • Eventually, infrastructure definitions themselves need conditionals • At that point, YAML either becomes a DSL nightmare or insufficient • Which makes me wonder whether trying to keep "infra definitions in YAML" is actually fighting Pulumi instead of using it properly Where I'm currently leaning (but unsure) Because of this, I'm starting to think: > Writing infrastructure definitions in a programming language might actually be the correct long-term choice. Not because it's more powerful, but because it avoids artificial constraints and DSL complexity. But I'm still uneasy about the implications. Our current operational model Given the above, the model we're gravitating toward is: W
Copy code
request
  → IDP (generate or modify git-based Pulumi code)
      → IDP (clone & apply via Automation API)
Which implies: • The IDP generates or modifies Pulumi programs (e.g.
index.ts
) • Those programs live in Git • Pulumi executes them via Automation API • The same repo can be operated via CLI when needed This works—but it feels heavy, and I'm not fully confident it's the right abstraction boundary. What I'd really like feedback on My core concern is this: Is it the right approach for an IDP to generate and modify programming language code (e.g. TypeScript) to persist infrastructure definitions in Git? If it were YAML, parsing and modifying would be straightforward. But generating and modifying actual programming language code from an IDP feels fundamentally more complex and fragile. • Is this a common or accepted pattern for Pulumi-based IDPs? • Is this an inevitable outcome of using Pulumi "correctly", or a sign we're overcomplicating things? • Are there simpler or more established patterns people use in practice for this problem? Any insights, war stories, or references would be hugely appreciated. Thanks in advance 🙏
c
The advantage of running Pulumi in a standard programming language is that you can do whatever you want. Why not embed your IDP golden paths into a standard IaC framework that is distributed internally? As long as what ends up running acts like a Pulumi deployment the world is your oyster.
No need to have complicated code generation when you can make a library that implements your standardized patterns 🙂
As a concrete example of what you can do: awhile back I was working on a system that would precompile Pulumi programs into executable artifacts. These artifacts had a special mode that would print the configuration schema instead of running normally. As part of CI/CD I would then export the schema and publish it so that deployment parameters could be set via a web UI. It also enabled me to do schema comparisons for environment upgrades & ensure that a particular deployment configuration was compatible with a particular artifact.
Also it seems that Pulumi is advertising itself for IDPs specifically. If you haven't seen this, might be worth looking into. Could give you some ideas at least. It might be that you don't need any fancy tooling at all, and you're just looking at creating a set of reusable components for your use case.
b
@prehistoric-egg-84122 I get to talk to a lot of people using Pulumi in very different ways and I've seen a few examples of people generating their own programs as part of an internal IDP project, and running this as a single stack. There are a couple of pain points that people seem to reach: 1. If you end up with thousands of resources in the stack, it takes time to process them all when you do subsequent updates so deployments take longer 2. You need to be very careful when making code changes as a small change in the code path can lead to resources being deleted unexpectedly because people don't check the preview properly So whilst what you're talking about is a very valid way of using Pulumi - after all, what's the point in allowing people to use very expressive languages if they can't do things like this, it doesn't come without its challenges. I'm not saying don't do what you're suggesting, I'm saying do think about how you approach it. Nate is correct that we do have some tooling that can help drive IDP goals built into Pulumi Cloud (and in our OSS offering) that you may find useful and may make your life easier so let me know if I can help to put you in touch with the right teams.
p
First of all, thank you very much for the thoughtful responses and for taking the time to help 🙂 We are already using Pulumi `ComponentResource`s to model our primary workloads, and this is how we currently operate in practice. For example, our services are fundamentally based on AWS ECS. All infrastructure required for an application to run—such as Route 53 records, ECR repositories, target groups, and so on—is implemented as a standardized
ComponentResource
that represents our canonical application setup, and the IDP consumes these ComponentResources to execute them as inline programs. That said, we still find ourselves with the concerns I described earlier, which is why I wanted to ask this question more explicitly. What IaC should guarantee (in our view) Regardless of tool choice, we believe IaC should ensure: • Infrastructure configuration always leaves artifacts (code + state remain for inspection, recovery, and audit) • The same infrastructure code must be operable via: ◦ CLI (for import, migration, emergency fixes) ◦ API / Automation (CI, IDP) • Common infrastructure patterns should be reusable and modular • Git should remain the source of truth Additional context on our approach To summarize my thinking, the code that lives in Git would ideally look something like this:
Copy code
// base workload
new CustomEcs()

// optional capabilities
new CustomS3()
new CustomRds()
new CustomKinesis()
new CustomRedis()
In other words, the core dilemma I'm grappling with is inline programs (constructing the Pulumi program purely in memory and discarding it) versus using Git as the system of record. When I mentioned "generating code" earlier, I was referring specifically to generating code like the above—just the control logic for invoking reusable components, nothing more. • This naturally raises another important question for us: • what is the safest and most maintainable way to generate or manage this kind of application-level Pulumi code? ◦ ex. using pulumi cli like pulumi new..~~ Any additional perspective—especially based on real-world experience—would be extremely helpful. Thanks again!