⚡ Promptolis Original · Coding & Development
👨🏫 Code Review Teacher
Not just what's wrong — what senior engineer's brain is pattern-matching to when they smell it.
Code Review Teacher — Not just what's wrong — what senior engineer's brain is pattern-matching to when they smell it. Setup: 4 min to try · Best AI: Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names. · Cost: Free, MIT-licensed.
Why this is epic
Most AI code reviewers tell you what to fix. This one teaches you the mental model a staff engineer uses, so next time you write the code right the first time.
Every finding includes the 'smell' — the pattern the reviewer is recognizing — plus the name of the anti-pattern, the failure mode it leads to in production, and a one-line heuristic you can carry forever.
It ranks findings by 'career impact' — which mistakes would actually cost you credibility in a real PR at a senior company vs. which are nitpicks.
📑 Page navigation + Key Takeaways Click to expand
📌 Key Takeaways
- What it is: Not just what's wrong — what senior engineer's brain is pattern-matching to when they smell it.
- Best for: Leveling up from mid-level to senior by learning what senior reviewers actually look for
- Time investment: 4 min to try setup, ~60 seconds in Claude output
- Recommended AI model: Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names.
- Cost: Free forever — MIT-licensed, no signup, no paywall
📑 On this page
- The prompt (copy-ready)
- How to use it (4 steps)
- Example input + output
- Common use cases
- Pro tips + variants
- FAQ
⚙️ At a glance
- Category:
- Coding & Development
- Setup time:
- 4 min to try
- Output time:
- ~60 seconds in Claude
- Best AI model:
- Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names.
- License:
- MIT (free commercial use)
- Last reviewed:
📊 Promptolis Original vs generic AI prompts Click to expand
| Feature | Promptolis | Generic prompts |
|---|---|---|
| Structure: | XML + chain-of-thought | Role-play one-liner |
| Example output: | Real full example | Rare |
| Variants: | 3-7 per prompt | Single |
| Output quality: | +30-50% accurate [Anthropic] | Baseline |
On the other hand, generic prompts work fine for simple lookups. Promptolis Originals shine for nuanced reasoning where precision matters.
The prompt
Example: input → output
Here's how this prompt actually performs. Real input below, real output from Claude Opus 4.
Language / stack: Python 3.11, FastAPI, Postgres via SQLAlchemy
Author experience level: 2.5 years professional, comfortable with Python and REST APIs, haven't worked much on high-traffic systems
Context: Production endpoint in a B2B SaaS. Handles ~200 req/sec at peak. This is for a billing-adjacent feature.
Intent: Given a customer_id, return their active subscriptions plus the total monthly cost. Called from the customer dashboard on every page load.
Code:
```python
@app.get("/customers/{customer_id}/subscriptions")
def get_subscriptions(customer_id: str, db: Session = Depends(get_db)):
customer = db.query(Customer).filter(Customer.id == customer_id).first()
if not customer:
return {"error": "not found"}
subs = db.query(Subscription).filter(Subscription.customer_id == customer_id).all()
active = []
total = 0
for s in subs:
if s.status == "active":
plan = db.query(Plan).filter(Plan.id == s.plan_id).first()
active.append({
"id": s.id,
"plan_name": plan.name,
"price": plan.price
})
total += plan.price
return {"customer": customer.name, "subscriptions": active, "total": total}
```
Code Review: Customer subscriptions endpoint — billing-adjacent, read-heavy, and currently a latency bomb
Verdict
Request changes. The logic is correct and I can see what you were going for — but this endpoint has an N+1 query, a broken error contract, and it touches money without a single test or type guarantee in sight. At 200 req/sec on a billing page, this will be your most-hit endpoint, and right now it's a pager waiting to buzz. The good news: every problem here is a well-known pattern with a clean fix, and once you internalize them you won't write this shape of code again.
Findings (ranked by career impact)
1. N+1 query in the hot loop — Blocker
The code:
for s in subs:
if s.status == "active":
plan = db.query(Plan).filter(Plan.id == s.plan_id).first()
What I'm pattern-matching to: The instant I see a DB call inside a for loop over DB results, my stomach drops. This is the single most common performance bug in ORM code and it's the one that makes senior engineers sigh audibly in review. One request → 1 + 1 + N queries. A customer with 12 subs is 14 round trips. At 200 rps, that's ~2800 queries/sec to Postgres for one endpoint.
Anti-pattern name: N+1 query / SELECT-in-loop.
Failure mode in production: Endpoint works fine in staging (small data). Ships. Works fine for most customers. Then your biggest customer — the one with 40 subscriptions — loads their dashboard and takes 4 seconds. Their CSM Slacks you. You add a cache. The cache gets stale. Now billing shows wrong numbers. This is how billing incidents start.
The fix: Join, or use selectinload:
subs = (db.query(Subscription)
.options(selectinload(Subscription.plan))
.filter(Subscription.customer_id == customer_id,
Subscription.status == "active")
.all())
Also push the status == "active" filter into SQL — don't fetch rows just to throw them away.
Heuristic to carry forever: If your ORM call is inside a loop, you've already written a bug. Pull it out or eager-load.
2. Money as a float — Blocker (this is the finance one)
The code:
"price": plan.price
...
total += plan.price
What I'm pattern-matching to: You're in a billing-adjacent endpoint and I can't tell from the code whether plan.price is a Decimal, float, or cents-as-int. If it's a float, you are one summation away from returning 29.990000000000002 to a customer. On a billing page.
Anti-pattern name: Floating-point money.
Failure mode in production: Customer sees $89.97000000001. Screenshots it. Tweets it. Support ticket. Or worse: you sum prices for invoicing and undercharge by a penny per customer per month, and finance notices in Q3.
The fix: Use Decimal end-to-end, or store cents as int. Type the response model with Pydantic so the contract is explicit:
class SubscriptionOut(BaseModel):
id: str
plan_name: str
price_cents: int
Heuristic to carry forever: Money is never a float. Ever. Not even once.
3. Error contract is a lie — Major
The code:
if not customer:
return {"error": "not found"}
What I'm pattern-matching to: Returning a 200 with an error key. The client sees HTTP 200 OK and has to introspect the body to know it failed. Every consumer of this API will eventually forget to check, and you'll get silent failures downstream.
Anti-pattern name: Envelope-based errors over HTTP / lying status codes.
Failure mode in production: Frontend shows 'Customer: undefined' because it happily parsed the error object as a customer. Or a retry layer doesn't retry because 200 means success.
The fix: raise HTTPException(status_code=404, detail="customer not found"). Let the framework do its job.
Heuristic to carry forever: HTTP status codes exist so clients don't have to read your mind. Use them.
4. No response model, no types on the boundary — Major
What I'm pattern-matching to: FastAPI's entire value proposition is typed boundaries, and this endpoint throws that away by returning a raw dict. Future-you adds a field, forgets to update the frontend, and nothing complains until a user does.
Failure mode in production: Silent schema drift. The API docs (which FastAPI generates from types) say nothing useful. New engineers guess at the shape.
The fix: Define a Pydantic response_model on the route. Now the contract is enforced and documented.
Heuristic to carry forever: The boundary of your service is a contract. Make the computer check it.
5. `customer_id: str` with no validation — Minor
If IDs are UUIDs, type them as UUID and FastAPI rejects garbage at the door. Saves a DB round trip on every malformed request and gives you a clean 422.
6. Naming: `subs`, `s`, `active` — Nit
In a 15-line function it's fine. I'd still write subscriptions and active_subscriptions because the cost of typing is zero and the cost of ambiguity compounds. Not worth blocking a PR on.
What You Did Well
- You separated the 'fetch' from the 'transform' mentally, even if the DB calls leaked into the loop. The shape of the function is right.
- You returned a computed
totalon the server instead of making the client sum prices. That's the correct call for money — one source of truth. - You used dependency injection for the DB session. A lot of 2-year engineers wire sessions globally and regret it.
The One Habit to Build
Treat every endpoint as a contract with a typed request and a typed response, and assume the database is the slowest thing in the room. Those two instincts — 'where are my types?' and 'how many queries is this?' — are 80% of what separates a mid-level backend engineer from a senior one. If you run every PR you write through those two questions before hitting submit, you'll level up faster than any book will take you.
Suggested Practice
Rewrite this endpoint with: (1) a Pydantic request & response model, (2) a single query using selectinload, (3) Decimal or integer cents for money, (4) proper HTTPException for errors, and (5) a pytest test that asserts exactly one SQL query is emitted (use sqlalchemy.event or pytest-postgresql's query counter). The last one is the killer exercise — once you've written a test that fails when an N+1 sneaks in, you start seeing them everywhere.
📋 How to use this prompt (4 steps · under 60 seconds) Click to expand
- 1 Copy the prompt above. Click "Copy prompt". XML-structured prompt now on clipboard.
- 2 Open ChatGPT, Claude, or Gemini. One-click launch above. Recommended: Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names..
-
3
Paste + fill placeholders. Replace
{curly braces}with your context. Specificity = quality. - 4 Run + iterate. Setup: 4 min to try. Output: ~60 seconds in Claude.
Common use cases
- Leveling up from mid-level to senior by learning what senior reviewers actually look for
- Pre-flighting a PR before humans see it, so you don't burn reviewer goodwill on dumb stuff
- Onboarding to a new language or framework and wanting feedback that teaches idioms
- Learning a codebase style by reviewing your own code against industry norms
- Tech lead training — seeing how to give feedback that educates instead of just corrects
- Interview prep — catching the habits that get flagged in coding interviews
- Reviewing AI-generated code before you commit it, since LLMs produce subtle smells
Best AI model for this
Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names.
Pro tips
- Paste the smallest self-contained unit possible — one function or one file. Teaching quality drops fast when the context is a 2000-line dump.
- Tell it your experience level honestly. 'I'm 2 years in, comfortable with Python, weak on concurrency' produces way better teaching than leaving it blank.
- Specify the context: production service, side project, interview exercise, or prototype. The bar is different and the teacher adjusts.
- If it flags something you disagree with, push back. Ask 'under what conditions would this actually matter?' — it's good at steelmanning both sides.
- Save the heuristics it gives you. After 10 reviews you'll have a personal style guide that's more useful than any book.
- For juniors: ask it to also rewrite one section in the 'senior' style, with inline comments explaining each decision.
Customization tips
- Paste ONE function or ONE file, not a whole repo. Teaching quality is inversely proportional to context size.
- Be honest about your experience level — 'senior but new to Rust' gets very different feedback than '2 years, all Python'. The teacher calibrates.
- Always include the production context. 'Prototype' vs '200 rps production' completely changes which findings are blockers vs nits.
- If you want to learn a specific skill (concurrency, testing, types), say so at the end of the intent field — e.g., 'especially interested in how I'm handling errors'.
- Run it on your own old code from 1–2 years ago. Seeing the smells you've since outgrown is the fastest way to internalize how reviewers think.
Variants
Interview Mode
Reviews as if it's a staff engineer on a coding interview loop — flags things that would cost you the offer vs. nitpicks.
Security Lens
Same teaching format but focused on security smells — auth, input validation, secrets, SSRF, injection — with the attacker's mental model.
Junior-to-Senior Coach
Assumes the author is early-career and explicitly names the 'senior habit' they need to build, with practice exercises.
Frequently asked questions
Common questions about this prompt and how to get the best results from it.
How do I use the Code Review Teacher prompt?
Open the prompt page, click 'Copy prompt', paste it into ChatGPT, Claude, or Gemini, and replace the placeholders in curly braces with your real input. The prompt is also launchable directly in each model with one click.
Which AI model works best with Code Review Teacher?
Claude Opus 4.1 or Sonnet 4.5. Opus is noticeably better at seeing architectural smells and explaining WHY a pattern is bad; Sonnet is fine for syntax-level review. Avoid smaller models — they tend to hallucinate pattern names.
Can I customize the Code Review Teacher prompt for my use case?
Yes — every Promptolis Original is designed to be customized. Key levers: Paste the smallest self-contained unit possible — one function or one file. Teaching quality drops fast when the context is a 2000-line dump.; Tell it your experience level honestly. 'I'm 2 years in, comfortable with Python, weak on concurrency' produces way better teaching than leaving it blank.
What does it cost to use this prompt?
The prompt itself is free, MIT-licensed, with no email signup required. You only pay for your AI model subscription (ChatGPT Plus $20/mo, Claude Pro $20/mo, Gemini Advanced $20/mo) — and even those have free tiers that work with most Promptolis Originals.
How is this different from PromptBase or PromptHero?
PromptBase sells prompts in a marketplace ($2-15 each). PromptHero focuses on image-generation prompts. Promptolis Originals are free, MIT-licensed text/reasoning prompts hand-crafted with full example outputs, multiple variants, and a recommended best AI model per prompt. We don't sell anything.
Explore more Originals
Hand-crafted 2026-grade prompts that actually change how you work.
← All Promptolis Originals