Mo Sharif
Back to writing

Architecture Diagram to Terraform, K8s, and Compose

In this article

An architecture diagram contains more than coordinates. A PostgreSQL node connected to an API says something about resources, configuration, and a dependency the application expects to exist.

That made infrastructure export a natural extension of Codelit's canvas. It also exposed an important limit: a diagram can generate useful scaffolding without knowing enough to deploy a working system.

Infrastructure export

translates a typed architecture graph into target-specific configuration that engineers review, complete, and validate before deployment.

An export pipeline maps graph types to target-specific resource templates, then fills supported properties and resolves relationships. The graph is an intermediate representation. It needs validation before generation and a clear way to report anything the selected target cannot express.

The same node may come from a prompt, manual editing, a GitHub repository analysis, or a Mermaid import. Its origin should not change the export contract.

That contract needs more than a label. "Database" does not specify engine, persistence, network access, backup policy, or credentials. If those details are missing, the exporter should ask, use a clearly labeled development preset, or mark the output incomplete.

Each target represents a different operating model. Compose assembles local containers, Terraform manages provider resources, and Kubernetes declares workloads and supporting cluster objects. A single visual node can expand into several resources, but there is no universal resources-per-node ratio.

Canvas conceptCompose exampleTerraform exampleKubernetes example
PostgreSQLContainer and named volumeManaged database and network dependenciesStatefulSet, Service, and storage
API serviceImage or build contextContainer service and task definitionDeployment and Service
Object storageCompatible local object-store serviceManaged bucketExternal object store or dedicated service
Public entry pointReverse proxyLoad balancer and listenerIngress or Gateway with a controller

A persistent volume is not a drop-in replacement for object storage. A database StatefulSet is not a managed database service. Those distinctions should survive the export instead of being flattened into a reassuring table.

An edge needs enough semantics to describe the interaction it represents: direction, protocol, port, identity, and dependency behavior. The exporter cannot safely infer all of that from line style or from the fact that two boxes are connected.

RelationshipWhat generation can help withWhat still needs a decision
API reads databaseHostname and connection configurationCredentials, allowed queries, pooling, retries
Service publishes eventsBroker endpoint and topic referencesDelivery guarantees, deduplication, buffering
Browser calls APIPublic origin or proxy routeCORS, authentication, TLS, deployment routing
Service calls serviceDiscovery and network configurationAuthorization, timeouts, policy enforcement

For Kubernetes, a Service gives discovery and routing; it does not by itself enforce which workloads may connect. NetworkPolicy requires a supporting network plugin. The export must distinguish a resource's existence from the policy actually being enforced.

The canvas's typed nodes and edges make these relationships inspectable. That is useful precisely because an engineer can challenge the mapping.

Compose can describe how containers start and connect, but it cannot supply application code or missing image behavior. Build contexts, environment-variable names, health endpoints, and runtime dependencies must match the actual services in the repository.

A browser cannot resolve a Compose service name such as "api" just because an nginx container can. A static frontend also does not automatically consume runtime environment variables. It needs a build-time value, runtime configuration mechanism, or reverse-proxy route.

Docker's startup-order documentation distinguishes a container being started from its dependency being healthy. Health-gated startup helps, but it does not replace reconnect logic when the database restarts after the API is already running.

A database workload needs matching selectors and pod labels, stable service discovery, storage, credentials, and a deliberate recovery strategy. A YAML fragment with a container and a volume is not a complete deployable database configuration.

Kubernetes documents the supporting requirements for StatefulSets, including stable network identity and persistent storage. A referenced Secret, Service, or storage class must actually exist and match the workload's expectations.

A sample missing pod labels or supporting resources can look complete while failing admission or startup. That is exactly the mismatch an exporter should catch before showing a download button.

For production, database operations also need tested backups, restore procedures, upgrade handling, and a clear owner. Generating YAML does not generate that operational capability.

An exporter should validate the graph, validate the generated format, and report environment-specific checks it could not perform. Each result should name the evidence it provides. A successful syntax check must not become a "production ready" badge.

CheckWhat it establishesWhat remains unknown
Graph validationSupported types and resolvable referencesWhether the architecture meets requirements
Compose configuration checkA coherent Compose modelWhether the application starts and behaves correctly
Terraform validationSyntax and internal consistencyRemote provider availability and account constraints
Terraform planProposed changes for selected inputs and stateApplication behavior after changes
Cluster-side dry runAdmission checks in that clusterWorkload readiness and runtime correctness
Isolated deployment testObserved behavior in the test environmentProduction conditions not represented there

HashiCorp explicitly limits what Terraform validation proves. That makes it valuable, not weak: a precise check is more useful than a broad claim it cannot support.

Generated output should expose decisions the graph cannot justify, including secrets, capacity, backups, access policy, and cost. Defaults need names and scope. "Development preset" is useful information; "sensible defaults" without an explanation is not.

Pin provider and module versions where appropriate. Include a README with required inputs, validation commands, known limitations, and cleanup instructions. Avoid implying that a generated backup setting proves recoverability.

Cost belongs in that handoff too. Design-time estimates can help compare options, but they are estimates with assumptions, not the bill the cloud provider promises to send.

Infrastructure export is valuable when it preserves intent and removes repetitive translation without concealing uncertainty. The outcome should be a reviewable starting point that an engineer can understand, modify, and test, not a shortcut around deployment judgment.

That is the part I want Codelit to get right: the diagram and the implementation should be connected by an inspectable mapping.

The useful promise is smaller than "draw it and deploy." Draw the system, carry its structure forward, and make the remaining decisions harder to miss.

Questions people actually ask

Can you generate infrastructure code from a diagram?
Yes, when the diagram carries typed nodes, explicit connections, and enough properties to map onto a target platform. The result is scaffolding, not evidence that the application will run. Missing images, secrets, network policies, and environment details still need engineering decisions.
Is generated infrastructure code production ready?
Not merely because it parses or passes a validator. Production readiness also depends on permissions, backups, recovery, monitoring, capacity, cost, and the behavior of the actual application. Review the generated plan and test it in an isolated environment before considering a production deployment.
Why do connections matter as much as nodes?
A node identifies a resource, but a connection describes how resources interact. Export needs protocol, port, direction, identity, and failure assumptions to translate that relationship safely. A plain arrow cannot establish all of those details, so missing information should remain explicit.
Does Terraform validation prove an export will deploy?
No. Terraform validation checks syntax and internal consistency after required providers and modules are installed. It does not validate remote services. A plan adds environment-specific checks, and applying and testing in the target environment provides a different level of evidence.
Will a generated Compose file start a working app?
Only if its referenced images or build contexts exist and the application supports the supplied configuration. Health-based dependencies can help with startup ordering, but services still need runtime retries and recovery. A healthy container is not proof that the full user workflow works.