The Prompt Engineering Cheat Sheet Every Developer Needs
Most developers interact with LLMs the same way they use a search engine. Type a vague question, hope for a good answer, and get frustrated when the output is wrong. The difference between getting mediocre results and getting production-quality output from an LLM is not the model — it is the prompt.
I use AI coding tools eight-plus hours a day. I have built AI agents, RAG pipelines, and full applications using only AI. Every single one of those projects required good prompts. Not clever prompts. Not tricky prompts. Structured, clear, intentional prompts.
This is the cheat sheet I keep coming back to.
The Golden Rule
LLMs do exactly what you ask them to do. If the output is bad, the prompt is bad. Before blaming the model, reread your prompt and ask yourself: would a senior developer with no context about my project understand exactly what I want from this instruction?
If the answer is no, rewrite the prompt.
Anatomy of a Good Prompt
Every effective prompt has these components, whether you write them explicitly or not:
- Role — who the AI should be
- Context — what it needs to know
- Task — what it should do
- Format — how the output should look
- Constraints — what it should avoid
You do not always need all five. But when your output is off, check which one you are missing.
Pattern 1: System Prompts
The system prompt is the most underused tool in a developer’s AI toolkit. It sets the behavior, personality, and constraints for the entire conversation.
Bad:
1
Write me a Go function to validate emails.
Good:
1
2
3
4
5
System: You are a senior Go developer. You write idiomatic Go code
following effective Go guidelines. You handle errors explicitly,
never use panic for control flow, and write table-driven tests.
User: Write a function to validate email addresses. Include tests.
The difference is massive. The first gives you a generic function that might use regex from Stack Overflow. The second gives you idiomatic Go with proper error handling and test coverage.
When to use it: Always. If you are using an API, set the system prompt. If you are using a chat interface, start your conversation by defining the role.
Pattern 2: Few-Shot Examples
Instead of describing what you want, show it. LLMs are exceptional pattern matchers. Give them two or three examples and they will extrapolate the pattern.
Instead of explaining:
1
2
Convert these API responses from snake_case to camelCase
and wrap them in a TypeScript interface.
Show the pattern:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Convert API responses to TypeScript interfaces. Follow this pattern:
Input: { "user_name": "string", "created_at": "datetime", "is_active": "boolean" }
Output:
interface User {
userName: string;
createdAt: Date;
isActive: boolean;
}
Input: { "order_id": "integer", "total_price": "float", "line_items": "array" }
Output:
interface Order {
orderId: number;
totalPrice: number;
lineItems: unknown[];
}
Now convert this:
{ "payment_method": "string", "billing_address": "object", "tax_rate": "float", "is_refunded": "boolean" }
When to use it: Code generation, data transformation, text formatting, or any task where the output follows a consistent structure.
Pattern 3: Chain-of-Thought
When you need the model to reason through a problem rather than jump to an answer, ask it to think step by step. This is not just a trick — it fundamentally changes how the model processes your request.
Without chain-of-thought:
1
2
Is this SQL query efficient?
SELECT * FROM orders WHERE user_id IN (SELECT user_id FROM users WHERE status = 'active')
With chain-of-thought:
1
2
3
4
5
6
7
8
9
Analyze this SQL query step by step:
1. What does each clause do?
2. What is the execution plan likely to look like?
3. Where are the potential performance bottlenecks?
4. What indexes would help?
5. Rewrite it if there is a more efficient approach.
Query:
SELECT * FROM orders WHERE user_id IN (SELECT user_id FROM users WHERE status = 'active')
The first might say “it looks fine” or suggest a vague improvement. The second walks through the actual analysis and gives you actionable optimization steps.
When to use it: Debugging, code review, architecture decisions, performance analysis — anything where reasoning matters more than recall.
Pattern 4: Structured Output
If you need JSON, YAML, or any structured format, define the schema explicitly. Do not hope the model guesses your structure.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Analyze this error log and return the result as JSON with this exact schema:
{
"error_type": "string (one of: runtime, network, auth, validation)",
"root_cause": "string (one sentence)",
"affected_service": "string",
"severity": "string (one of: critical, high, medium, low)",
"suggested_fix": "string (actionable steps)",
"related_errors": ["string"]
}
Error log:
[2026-03-08 14:23:01] ERROR PaymentService: Connection refused to stripe-api.internal:443
[2026-03-08 14:23:01] ERROR PaymentService: Retry 1/3 failed
[2026-03-08 14:23:03] ERROR PaymentService: Retry 2/3 failed
[2026-03-08 14:23:05] CRITICAL PaymentService: All retries exhausted. Circuit breaker opened.
When to use it: API integrations, data pipelines, log analysis, CI/CD automation — anywhere the AI output feeds into another system.
Pattern 5: Constraints and Negative Prompts
Tell the model what NOT to do. This is surprisingly effective at eliminating common failure modes.
1
2
3
4
5
6
7
8
Refactor this React component to improve readability.
Constraints:
- Do NOT change the component's public API (props interface stays the same)
- Do NOT add new dependencies
- Do NOT split into multiple files
- Do NOT add comments explaining obvious code
- Keep the total line count within 20% of the original
Without constraints, the model might refactor your 50-line component into three files with two new npm packages and comments on every line. Constraints keep the output practical and review-friendly.
When to use it: Code refactoring, writing documentation, generating migrations — any task where the model’s default behavior tends to over-engineer.
Pattern 6: Iterative Refinement
Do not try to get the perfect output in one shot. Use the conversation.
1
2
3
4
5
6
7
8
9
10
Prompt 1: "Write a Go middleware for rate limiting HTTP requests."
Prompt 2: "Good. Now make it use Redis instead of in-memory storage."
Prompt 3: "Add per-user rate limits based on the API key in the
Authorization header."
Prompt 4: "Add a sliding window algorithm instead of fixed window.
Include the X-RateLimit-Remaining and X-RateLimit-Reset headers
in the response."
Each prompt builds on the previous context. You end up with a sophisticated rate limiter, but each step was simple and reviewable. This is how I built entire applications with AI — not in one giant prompt, but in a guided conversation.
When to use it: Always, for anything non-trivial. One massive prompt rarely beats an iterative conversation.
Pattern 7: Role-Based Personas
Different roles produce different outputs. Use this intentionally.
| Role | Best For |
|---|---|
| “Senior backend engineer” | Architecture, API design, performance |
| “Security auditor” | Finding vulnerabilities, OWASP checks |
| “Tech lead doing code review” | Style, maintainability, team conventions |
| “QA engineer” | Edge cases, test scenarios, failure modes |
| “DevOps engineer” | Deployment, CI/CD, infrastructure |
| “Technical writer” | Documentation, README files, API docs |
Example:
1
2
3
4
5
You are a security auditor reviewing a fintech application.
Analyze this authentication endpoint for vulnerabilities.
Focus on OWASP Top 10 issues. For each finding, provide
the severity, the specific line or pattern that is vulnerable,
and the recommended fix.
This produces dramatically different (and more useful) output than “review this code.”
Pattern 8: Template Prompts
For tasks you do repeatedly, create reusable templates. I keep a library of these for common development tasks.
Code Review Template:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Review this [LANGUAGE] code as a senior developer.
Check for:
1. Bugs or logic errors
2. Security vulnerabilities
3. Performance issues
4. Readability and naming
5. Missing error handling
For each issue found:
- Severity: critical / major / minor / nit
- Line reference
- What is wrong
- How to fix it (with code)
If the code is clean, say so. Do not invent issues.
Code:
[PASTE CODE]
Bug Diagnosis Template:
1
2
3
4
5
6
7
8
9
10
11
I have a bug in my [LANGUAGE] application.
Expected behavior: [WHAT SHOULD HAPPEN]
Actual behavior: [WHAT HAPPENS INSTEAD]
Steps to reproduce: [STEPS]
Error message (if any): [ERROR]
Relevant code:
[PASTE CODE]
Diagnose the root cause step by step, then provide the fix.
When to use it: Any repeated workflow. Save these as snippets, MCP tools, or even CLI agent commands.
Pattern 9: Output Calibration
When the model’s output length or detail level is wrong, calibrate it explicitly.
1
2
3
4
5
Explain Kubernetes pod networking.
- Target audience: senior developers who know Docker but not K8s
- Length: 3 paragraphs maximum
- No analogies or metaphors
- Include one concrete example with actual IP addresses
Without calibration, you get a 2000-word essay that starts with “Kubernetes is a container orchestration platform…” and loses the reader by paragraph three.
When to use it: Documentation, explanations, summaries, changelogs — any text where length and audience matter.
The Prompt Engineering Stack for Developers
Here is how I think about prompts in layers, from most to least important:
-
Clarity — Can the model understand exactly what you want? If your prompt is ambiguous to a human, it is ambiguous to the model.
-
Context — Does the model have enough information? Include relevant code, error messages, file structures, and constraints.
-
Structure — Is your prompt organized? Numbered lists, sections, and explicit schemas beat wall-of-text prompts every time.
-
Examples — Have you shown what good output looks like? Two examples are worth a hundred words of description.
-
Iteration — Are you refining in conversation? The best outputs come from multi-turn conversations, not single prompts.
Common Mistakes
Prompt too vague: “Make this code better” — better how? Faster? More readable? More secure? Be specific.
No context: Asking the model to fix a bug without showing the error message or the surrounding code. The model is not psychic.
Over-prompting: Writing a 500-word prompt for a task that needs one sentence. If the task is simple, the prompt should be simple.
Not iterating: Giving up after one bad response instead of refining. The first response is a draft, not a deliverable.
Ignoring the system prompt: Using chat interfaces without setting a role. You are leaving the most powerful tool on the table.
Final Thought
Prompt engineering is not a separate skill from software engineering. It is software engineering applied to a new interface. The same principles that make good code — clarity, structure, specificity, iteration — make good prompts.
The developers who treat AI tools as magic boxes will keep getting inconsistent results. The developers who treat prompts as code — version them, template them, iterate on them — will build things the first group cannot even imagine.
Stop guessing. Start engineering your prompts.