Prompt Patterns for Developers

# Prompt Patterns for Developers

If you’re still typing “write me some code” into ChatGPT, you’re leaving massive productivity gains on the table. Prompt patterns are reusable structures that transform vague requests into precise, predictable outputs. They’re not hacks—they’re engineering discipline applied to AI interaction.

This isn’t about tricking the model. It’s about communicating intent clearly enough that you get exactly what you need, when you need it. Here are six patterns that actually work in real development workflows.

## The Scaffold Pattern: Get Structured Output Every Time

The scaffold pattern gives the model a framework for its response. Instead of hoping for JSON, you provide the structure and let the model fill in the blanks.

“`python
# Instead of this vague prompt:
# “Give me a Python function to process user data”

# Use the scaffold pattern:
prompt = “””Generate a Python function with the following specification:

INPUT:
– user_id: string
– data: dict with keys ‘name’, ’email’, ‘age’

OUTPUT:
– Return a dict with keys ‘user_id’, ‘processed_name’, ’email_hash’, ‘age_group’
– ‘processed_name’: title case, stripped
– ’email_hash’: SHA256 hex digest of lowercase email
– ‘age_group’: ‘minor’ if age < 18, 'adult' otherwise CONSTRAINTS: - Use only standard library (hashlib, re) - Include type hints - Add docstring Return ONLY the code, no explanations.""" ``` The model knows exactly where to put each piece. No more parsing prose for the data you need. This pattern shines when you're building pipelines that consume LLM output programmatically. ## The Chain-of-Thought Pattern: Show Your Work When you need the model to solve complex problems—debugging, architecture decisions, or multi-step refactoring—force explicit reasoning before the final answer. This isn't about being nice to the model. It's about catching errors in the model's thinking before they become bugs in your codebase. ```python prompt = """You are debugging a race condition in a Python asyncio application. PROBLEM: The counter sometimes shows incorrect values under concurrent load. CODE: ```python class Counter: def __init__(self): self.value = 0 async def increment(self): current = self.value # READ await asyncio.sleep(0.001) # SIMULATED I/O self.value = current + 1 # WRITE ``` TASK: 1. Identify the race condition (explain the specific interleaving) 2. Explain why the current code fails 3. Provide a fixed implementation using asyncio.Lock Show your reasoning step-by-step before presenting the solution.""" ``` The reasoning appears in the output. You can verify the logic before applying the fix. If the reasoning is wrong, the solution is probably wrong too. ## The Role-Based Pattern: Context Without Conversation History Don't make the model guess what kind of expertise you need. Assign a role that constrains the model's knowledge domain and response style. This pattern is particularly effective for code review and security analysis. ```python prompt = """ROLE: Senior security engineer with expertise in OWASP Top 10 CONTEXT: You are reviewing a Flask application's authentication module before production deployment. CODE TO REVIEW: ```python @app.route('/api/login', methods=['POST']) def login(): data = request.json user = db.query("SELECT * FROM users WHERE email = ?", data['email']) if user and user['password'] == data['password']: session['user_id'] = user['id'] return {'status': 'ok'} return {'error': 'Invalid credentials'}, 401 ``` TASK: 1. Identify ALL security vulnerabilities 2. Rate severity (Critical/High/Medium/Low) 3. Provide concrete fixes with code Focus on findings a competent developer would miss.""" ``` The role primes the model to apply specific knowledge. It also sets expectations for output format—senior engineers give prioritized, actionable feedback, not wishy-washy suggestions. ## The Few-Shot Pattern: Examples Beat Instructions When format matters more than explanation, show don't tell. The few-shot pattern provides concrete examples of input-output pairs, letting the model infer the pattern without explicit rules. ```python prompt = """Parse these log entries into structured JSON. EXAMPLES: Input: "2026-01-15 14:32:01 ERROR [auth.service] Failed login attempt for user admin" Output: {"timestamp": "2026-01-15T14:32:01", "level": "ERROR", "component": "auth.service", "message": "Failed login attempt for user admin"} Input: "2026-01-15 14:33:45 INFO [payments] Payment processed: $127.50 for order #8842" Output: {"timestamp": "2026-01-15T14:33:45", "level": "INFO", "component": "payments", "message": "Payment processed: $127.50 for order #8842"} Input: "2026-01-15 14:35:12 WARNING [cache] Redis connection timeout after 5000ms" Output: {"timestamp": "2026-01-15T14:35:12", "level": "WARNING", "component": "cache", "message": "Redis connection timeout after 5000ms"} YOUR TASK: Input: "2026-01-15 14:40:00 ERROR [database] Query timeout: SELECT * FROM large_table" Output:""" ``` Three examples establish the pattern. The model extracts the structure (timestamp, level, component, message) without you writing a parser spec. This works remarkably well for extracting data from unstructured text. ## The Template Pattern: Reusable Prompt Components Build prompts like you build code—compose from reusable parts. The template pattern treats prompts as parameterized functions, reducing repetition and ensuring consistency across your AI-assisted workflow. ```python def code_review_prompt(repo_context: str, changed_files: list[str]) -> str:
return f”””ROLE: Technical lead conducting a code review

REPOSITORY CONTEXT:
{repo_context}

CHANGED FILES:
{chr(10).join(f”- {f}” for f in changed_files)}

REQUIRED CHECKS:
1. Logic correctness
2. Error handling completeness
3. Performance implications
4. Security vulnerabilities

OUTPUT FORMAT:
For each file with issues:
“`## {{filename}}
### Issues
– [Severity] Description

### Recommended Fix
“`python
# code here
“`
“`

For each file without issues:
## {{filename}}
No issues found.
“””

# Usage
prompt = code_review_prompt(
repo_context=”E-commerce API built with FastAPI”,
changed_files=[“auth.py”, “orders.py”, “products.py”]
)
“`

Templates become your team’s standard review process. Same expectations, every time. You can version them, test them, and improve them systematically.

## The Debug-Iterate Pattern: Refine Through Conversation

Raw prompts rarely produce perfect output on the first try. The debug-iterate pattern treats AI interaction as a feedback loop, not a single-shot request. The key is knowing what to fix and how to ask for it.

“`python
# First attempt – got code but wrong approach
prompt = “Write a function to find the longest substring without repeating characters”
# Output: Uses set-based sliding window (correct approach, but verbose)

# Iteration 1 – specify constraints
prompt = “””Write a function to find the longest substring without repeating characters.

REQUIREMENTS:
– Use dictionary-based sliding window (not set-based)
– Time complexity must be O(n)
– Return both the length and the substring

CONSTRAINT: No external packages, pure Python only.”””
# Output: Dictionary approach, O(n), returns length and substring

# Iteration 2 – need it for a specific context
prompt = “””For the dictionary-based sliding window solution:
1. Add type hints
2. Add a main block with test cases
3. Wrap in a class called StringAnalyzer
4. Add brief inline comments explaining the window logic”””
# Final output: Ready-to-use class with tests
“`

Each iteration narrows the solution space. You’re not arguing with the model—you’re progressively constraining until it hits the target. This pattern is essential for complex refactoring tasks where the first output is directionally correct but not production-ready.

## Key Takeaways

– **Scaffold patterns** give structure; the model fills in the blanks. Use when you need programmatic output.
– **Chain-of-thought** forces reasoning visibility. Critical for debugging and architecture decisions.
– **Role-based prompts** constrain knowledge domain and set output expectations.
– **Few-shot examples** beat verbose instructions for format extraction tasks.
– **Template prompts** compose and version like code—build your team’s standard library.
– **Iterate don’t iterate**—refine with specific constraints, not vague “make it better” requests.

## Next Steps

1. Pick one pattern from this list. Apply it to your next coding task today.
2. Build a personal prompt template library in a markdown file. Add to it as you find patterns that work.
3. The next time you get a bad LLM response, don’t regenerate—iterate. Refine with specific constraints.
4. If you’re leading a team, standardize your prompt patterns in a shared doc. Consistency compounds.

The developers getting the most from AI aren’t using better models—they’re communicating better. These patterns are your syntax. Use them.