The three prompt patterns I actually use in production
After shipping AI in four companies where wrong answers cost real money, I've stopped reaching for clever prompt engineering and started reaching for three patterns. That's it. Three.
↻Revised 1 time — last on 2025.09.30· open
- 2025.09.30Removed the section about chain-of-thought prompting — by late 2025, the frontier models reason without being asked and the old 'let's think step by step' incantation became noise.
After shipping AI in four companies where wrong answers cost real money, I've stopped reaching for clever prompt engineering and started reaching for three patterns. That's it. Three. Everything else is decoration.
These patterns are boring. They're also the ones that survive contact with production.
1. Structured output as the interface
Every time I'm tempted to "just parse the response," I remind myself that the model will produce JSON-adjacent-but-not-quite-JSON at least 0.5% of the time, and that's enough to break a pipeline in the middle of the night. So: A response that conforms to a strict schema (JSON-with-types) rather than free-form prose you have to parse heuristically. OpenAI calls it response_format; Anthropic gets it via tool use.. Always. Use the provider's native schema support — OpenAI's response_format, Anthropic's tool use, or whatever else.
The mental model shift is this: your prompt is not a conversation with the model. Your prompt is the body of an API call that happens to be written in English. Treat the response the same way you'd treat a REST response — as a typed payload, validated at the boundary, never parsed heuristically.
Extract the company name and Q3 revenue from this paragraph as a JSON object with fieldscompany(string) andrevenueMillions(number)."Acme Corp reported Q3 revenue of $12.4M, up 18% year over year."Return only the JSON, no surrounding prose.
```json { "company": "Acme Corp", "revenueMillions": 12.4 } ```
2. Role priming with concrete negatives
"You are a helpful assistant" is not a system prompt. It's a wish.
What actually works: naming what the assistant is not supposed to do, with concrete examples. "You help developers write PostgreSQL queries. You do not suggest ORMs. You do not recommend migrating to MongoDB. If the user asks about NoSQL, redirect them to PostgreSQL's JSONB features." The negatives do more work than the positives.
You are a senior PostgreSQL engineer. You help developers write efficient PostgreSQL queries.You do not suggest ORMs. You do not recommend migrating to MongoDB. If the user asks about NoSQL, redirect them to PostgreSQL's JSONB features.User: I have a JSON column with nested data. What's the cleanest way to query a nested field?
# Querying Nested JSON in PostgreSQL For a JSON column with nested data, here are the cleanest approaches: ## Using JSONB (Recommended) If you're using **JSONB** (which you should for new projects), use the `->` and `->>` operators: ```sql -- Get the nested value as JSONB SELECT data->'user'->'profile'->'name' as name FROM my_table; -- Get the nested value as TEXT SELECT data->>'user'->>'profile'->>'name' as name FROM my_table; ``` ## Filtering on Nested Fields ```sql -- Find records where nested field equals a value SELECT * FROM my_table WHERE data->>'user'->>'email' = 'user@example.com'; -- Using JSONB comparison (more efficient) SELECT * FROM my_table WHERE data->'user'->>'email' = 'user@example.com'; ``` ## Using jsonb_extract_path() for Complex Paths ```sql -- More readable for deeply nested paths SELECT jsonb_extract_path(data, 'user', 'profile', 'name') as name FROM my_table; -- As text SELECT jsonb_extract_path_text(data, 'user', 'profile', 'name') as name FROM my_table; ``` ## Best Practices - **Use JSONB, not JSON** — JSONB is faster, supports indexing, and has more operators - **Create a GIN index** for frequent queries: ```sql CREATE INDEX idx_data_gin ON my_table USING GIN (data); ``` - **Extract to columns** if you query the same nested field repeatedly — it's faster than JSON extraction What's your specific use case? I can suggest more targeted optimizations.
I learned this the hard way at Rabobank, where a polite "helpful assistant" prompt kept confidently inventing API endpoints that didn't exist. Adding three lines of "do not hallucinate API paths; if you're not sure, say so" cut the hallucination rate to near zero.
3. Few-shot examples as the spec
The cheapest way to specify a task is to write two examples of input and expected output, and paste them directly into the prompt. Not instructions. Two to five demonstrations beats a paragraph of rules every time. The model is a pattern-completion engine — feed it patterns, not specifications..
This is particularly powerful for classification and extraction tasks where the rubric is hard to articulate but easy to demonstrate. I can write "classify this customer email as 'billing', 'technical', or 'escalation'" in a prompt, but the model will drift. If I show it two examples of each category, the drift disappears.
What I don't do anymore
I don't use The model's randomness knob. 0 picks the single highest-probability token; higher values widen the distribution. In production I use 0.3 for a sane middle — enough variance to avoid robotic phrasing, not enough to hallucinate. 0. I use temperature 0.3. Determinism is a lie at scale; what you want is consistent shape (hence structured output) with reasonable variance in word choice.
I don't pre-write the entire response structure in the prompt. Overfit prompts break when the input shifts slightly. Write the minimum that gets you reliable output, then stop.
These three patterns cover maybe 80% of production work. The other 20% is boring engineering — retries, rate limits, caching, evals — which are not prompt problems.
- Structured output
- Getting the model to return a strictly-typed object (JSON-with-schema) rather than prose you have to parse after the fact.
- Few-shot
- A prompting technique where you include 2-5 examples of the desired behavior inline, to demonstrate the task rather than describe it.
- Temperature
- The model's randomness knob. 0 = always the same tokens, 1 = more creative. In production I use 0.3 for a sane middle.