Prompt Patterns for Writing Better Code

Khimananda Oli 8 min read Virtualization
Prompt Patterns for Writing Better Code

By Khimananda Oli | Last reviewed: August 2026

Generating production-grade infrastructure or application logic via AI requires more than casual conversation; it demands structured prompt patterns for writing better code that constrain the model’s output space. Without explicit context, version pinning, and security guardrails, Large Language Models (LLMs) frequently hallucinate deprecated flags or invent insecure configurations that fail in real environments. This guide provides battle-tested templates and architectural mental models specifically for DevOps engineers and developers who need reliable, audit-ready code rather than generic snippets. If you are new to this domain, start with my overview on prompt engineering for DevOps engineers before applying these advanced patterns.

Vague Request"Fix my K8s YAML"❌ High Hallucination RiskApply PatternStructured Prompt• Role: SRE / SecOps• Version: K8s 1.31• Constraint: No root• Output: Validated YAML✅ Production Ready
Transitioning from vague requests to structured prompt patterns for writing better code significantly reduces errors and improves security compliance.

How do you structure prompt patterns for writing better code?

The most common failure mode I see when teams adopt AI-assisted coding is treating the LLM as a search engine rather than a reasoning engine. To get usable output, you must front-load context. A robust prompt pattern always includes four distinct components: Persona, Context, Constraints, and Output Format. When I ask an LLM to generate Terraform modules, I never say "create an S3 bucket." Instead, I specify: "Act as a Senior Cloud Architect specializing in SOC 2 compliance. Generate a Terraform module for AWS S3 using provider version ~> 5.0. Enforce server-side encryption with KMS, block public access, enable versioning, and tag all resources with 'Environment' and 'CostCenter'. Output only HCL code with inline comments explaining security decisions."

This level of specificity serves two purposes. First, it anchors the model's probabilistic generation to a specific subset of its training data related to modern, secure practices. Second, it creates a verifiable contract. You can immediately check if the output meets the stated constraints. For teams adopting generating IaC with AI guardrails, this structured approach is mandatory. It transforms subjective code review into objective constraint validation. Always pin versions explicitly; an LLM trained on data up to 2024 might default to Terraform 1.5 syntax even if your state file requires 1.9 features, causing subtle plan drift.

The Context-Constraint Matrix

I recommend maintaining a personal or team-level "context library" — a repository of pre-vetted prompt blocks. When you need to generate code, assemble these blocks rather than typing from scratch. Include your organization’s standard tagging policy, approved CIDR ranges, naming conventions, and banned services. This reduces token waste and ensures consistency across different team members’ prompts. Remember that prompt patterns for writing better code are reusable assets, not disposable chat messages.

What are the best prompt patterns for writing better code in Infrastructure as Code?

Infrastructure as Code presents unique challenges because bugs manifest as security vulnerabilities or billing disasters rather than simple runtime errors. The most effective pattern here is the "Secure-by-Default Skeleton." Never ask the LLM to write infrastructure from zero. Instead, provide a secure skeleton or reference architecture and ask it to fill in specific business logic within those boundaries.

<!-- Example: Secure EKS Module Prompt Pattern -->
ROLE: Principal DevOps Engineer, AWS EKS Specialist
TASK: Create an EKS cluster module for a fintech workload
CONSTRAINTS:
- EKS version: 1.31
- Node groups: Managed, t3.medium, min 2 max 5
- Networking: Private subnets only, no public API endpoint
- Security: IRSA enabled, Pod Identity Agent installed
- Compliance: All logs to CloudWatch, encryption at rest/transit
- DO NOT: Use default VPC, enable public endpoint, use node IAM roles
OUTPUT: Single main.tf with validation blocks and security comments

This pattern forces the model to operate within a safety corridor. Notice the explicit "DO NOT" constraints. LLMs are sycophantic; they tend to agree with implicit assumptions unless explicitly forbidden. By listing anti-patterns, you actively suppress common misconfigurations. In my experience helping Nepal-based fintech companies achieve compliance, this negative-constraint technique has prevented more issues than positive instructions alone.

Initial Structured PromptLLM GenerationValidateFail / RefinePassCommit to Repo
Effective prompt patterns for writing better code require an iterative validation loop where failures trigger refined prompts rather than manual fixes.

Handling State and Dependencies

When generating code that interacts with existing infrastructure, always paste relevant state excerpts or dependency graphs into the prompt context window. An LLM cannot infer your VPC ID or existing IAM role ARNs. Providing these values prevents placeholder hallucinations like vpc-12345678. For complex dependencies, consider using AI to write Terraform and Kubernetes YAML in conjunction with tools like terraform plan -json fed back into the chat as context for correction.

How do prompt patterns for writing better code differ between application and infrastructure development?

While the core principles remain consistent, the tolerance for ambiguity differs drastically. Application code often benefits from creative exploration, whereas infrastructure demands deterministic precision. Understanding these differences helps you select the right pattern variant.

DimensionApplication Code PromptsInfrastructure Code Prompts
Primary GoalFunctionality, readability, performanceSecurity, compliance, cost-efficiency, stability
Version SensitivityModerate (framework APIs evolve)Critical (provider breaking changes cause outages)
Context RequirementBusiness logic, data models, UI specsNetwork topology, IAM policies, compliance frameworks
Validation MethodUnit tests, linting, type checkingPlan analysis, policy-as-code (OPA), security scanning
Risk ProfileBugs, tech debt, UX issuesData breaches, regulatory fines, service downtime
Recommended PatternTest-Driven Generation, Refactoring ChainsSecure Skeleton, Constraint Lists, Audit Trails

In application development, I frequently use "Test-First Prompting." Ask the LLM to write failing tests for a feature before generating the implementation. This aligns the model’s understanding of requirements with executable specifications. For infrastructure, however, tests are slower and more expensive. Instead, use "Policy-First Prompting": ask the model to generate the OPA Rego policy or Sentinel rule first, then generate the Terraform that passes it. This inverts the traditional workflow but dramatically increases confidence in the output.

How can you validate outputs from prompt patterns for writing better code?

Trust but verify is insufficient for AI-generated code; you must automate verification. Never copy-paste LLM output directly into production repositories without passing through automated gates. Integrate validation tools into your IDE or CI pipeline that specifically target LLM failure modes. Tools like tflint, kubeval, checkov, and semgrep should run immediately after generation.

A powerful meta-pattern is "Self-Correction Loops." After receiving initial code, prompt the model: "Review this code against CIS Benchmark v2.0 for EKS. List every violation, explain why it fails, and provide the corrected code block." This leverages the model’s broader knowledge base for auditing while keeping the generation focused. Be aware that self-correction is not foolproof; always pair it with external tooling. For teams implementing AI code review in CI pipelines, this dual-layer validation catches both syntactic errors and semantic security flaws.

Documentation as Validation

Require the LLM to generate documentation alongside code. Ask for Architecture Decision Records (ADRs) or threat models as part of the same prompt. If the model cannot coherently explain why a security group allows port 22 from 0.0.0.0/0, that is a signal the configuration is likely wrong. Documentation generation acts as a reasoning stress test. In regulated environments, this documentation also serves as audit evidence, killing two birds with one stone.

Naive ApproachPrompt → Copy → Deploy• No version pins• Implicit defaults• Manual review onlyResult: Drift & VulnerabilitiesValidated PatternPrompt → Scan → Fix → Commit• Explicit constraints• Automated policy checks• Self-correction loopsResult: Compliant & StableAdopt Patterns
Adopting validated prompt patterns for writing better code shifts the workflow from risky copy-paste to systematic, automated assurance.

When should you avoid using prompt patterns for writing better code?

Despite their power, these patterns have limits. Do not rely on LLMs for novel cryptographic implementations, proprietary protocol reverse-engineering, or highly sensitive credential handling. The model’s training data cutoff means it lacks awareness of zero-day vulnerabilities disclosed last week. Always cross-reference generated security configurations against current CVE databases and vendor advisories. Additionally, avoid using prompts for legacy systems with undocumented behavior; the model will confidently generate plausible-looking but completely incorrect COBOL or mainframe JCL based on generalized patterns rather than your specific environment’s quirks.

For teams in Nepal working with local payment gateways like eSewa or Khalti, be especially cautious. Global LLMs have minimal training data on these specific APIs. In such cases, use the LLM for structural scaffolding and boilerplate, but manually implement the integration logic using official SDK documentation. Supplementing prompts with retrieved documentation via RAG can help, but human verification remains non-negotiable for region-specific integrations.

Building Your Practice with Prompt Patterns for Writing Better Code

Mastering prompt patterns for writing better code is an iterative discipline, not a one-time setup. Start by documenting your successful prompts in a shared team wiki or repository. Treat prompts as code: version them, review them, and retire them when underlying platforms change. Measure effectiveness by tracking reduction in review cycles and post-deployment incidents. As you refine your patterns, you will find that the quality of AI-generated code becomes predictable and trustworthy. If you need help establishing these workflows for your team or auditing your current AI-assisted development practices, reach out to discuss your specific infrastructure challenges.

Frequently Asked Questions

Persona assignment, chain-of-thought reasoning, and few-shot examples remain top patterns. Specifying language version, framework constraints, and testing requirements upfront prevents generic outputs. Combining structural templates with explicit negative constraints yields production-ready code faster than open-ended requests.

Define the Laravel version, specify Eloquent relationships, and mandate input validation rules. Request CSRF protection and parameterized queries explicitly. Include a security review step asking the model to identify potential SQL injection or mass assignment vulnerabilities before finalizing the implementation.

Yes. Grounding prompts with specific tool versions like Terraform 1.9 or Ansible 2.16 limits fabrication. Providing existing configuration snippets as context and requesting syntax validation commands forces the model to adhere to real documentation rather than inventing deprecated flags or non-existent modules.

Zero-shot relies solely on instructions while few-shot provides input-output examples. Few-shot significantly improves accuracy for complex logic or proprietary internal APIs by demonstrating expected patterns. Use few-shot when standard documentation is insufficient or when enforcing specific team coding standards.

Paste the erroneous code back into the prompt with the specific error message. Ask the model to explain the root cause before fixing it. This chain-of-debugging pattern prevents superficial patches and ensures the underlying logic flaw is addressed in subsequent iterations.

Modular prompting works best for IaC. Break requests into variable definitions, resource blocks, and output configurations separately. Specify cloud provider API versions and compliance tags explicitly. Asking for dependency graphs and state management strategies prevents circular dependencies and ensures idempotent deployments across environments.

It forces the model to outline logic steps before writing syntax. This reduces off-by-one errors and edge case oversights in sorting or data processing algorithms. Explicitly requesting pseudocode first creates a verifiable blueprint that makes the final Python or Go implementation more reliable and testable.

Negative constraints prevent unwanted patterns like global variables or synchronous I/O. Stating what not to do is often more effective than positive instructions alone. They act as guardrails that keep generated code aligned with architectural decisions and performance budgets without requiring extensive post-generation refactoring.

Provide the source function and specify the testing framework like PHPUnit or Jest. Request boundary value analysis, null checks, and mock dependencies explicitly. Asking for test descriptions before code ensures coverage maps to business logic rather than just achieving arbitrary line coverage metrics.

Legacy modernization requires context-heavy prompts including original documentation and migration targets. Patterns must account for deprecated features and backward compatibility. Stepwise refactoring prompts that isolate single responsibilities reduce risk compared to monolithic rewrite requests that often introduce subtle behavioral regressions in critical systems.

Keep system instructions under 500 tokens and context under 4000 tokens for optimal coherence. Exceeding context windows degrades instruction following. Summarize large codebases into interface definitions rather than pasting entire files to maintain focus on the specific generation task at hand.

Reference specific style guides like PSR-12 or PEP8 by name and version. Include a linting configuration snippet in the prompt context. Requesting formatted output that passes automated checkers ensures consistency without manual cleanup and integrates smoothly into CI pipelines.

Entity-relationship prompting with cardinality constraints produces better schemas. Specify normalization level, indexing strategy, and foreign key behaviors. Asking for migration scripts alongside DDL ensures the design is implementable and accounts for data integrity rules specific to PostgreSQL or MySQL versions currently in production.

Always run static analysis tools like SonarQube or Semgrep on AI output. Prompt patterns should include requests for threat modeling and OWASP compliance checks. Treat generated code as untrusted until verified through automated scanning and peer review regardless of how confident the model appears.

Vague requirements, missing version constraints, and ignoring error handling are top failures. Overloading single prompts with multiple unrelated tasks causes context dilution. Failing to iterate based on feedback loops results in mediocre output that requires more effort to fix than writing manually from scratch.