Backend SWE

AI · Network · API · Data Structures · Database · Python · FastAPI · Testing · OOP · Docker · Behavioral

01
AI Integration
How would you integrate OpenAI API into a backend?
+
Key steps: Install the SDK (pip install openai), store API key in env vars, create a service layer to wrap calls. Use openai.chat.completions.create() with model, messages, and temperature.

Production considerations: retry logic with exponential backoff for rate limits, streaming responses for better UX, token budgeting to control costs, async calls with httpx to avoid blocking, structured outputs via function calling or JSON mode, and logging every request/response with a correlation ID.
02
AI Integration
What are tokens?
+
Tokens are the units LLMs use to process text — roughly 4 characters or ¾ of a word in English. "ChatGPT is great!" ≈ 6 tokens.

Why it matters: API costs are per token (input + output), context windows have token limits (GPT-4 = 128k). Use tiktoken to count tokens programmatically before building features.
03
Coding Task
Build an endpoint that summarizes text using AI.
+
@app.post("/summarize")
async def summarize(text: str):
    response = await openai_client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "Summarize concisely."},
            {"role": "user", "content": text}
        ],
        max_tokens=300
    )
    return {"summary": response.choices[0].message.content}
Add in production: input length validation, rate limiting per user, cost tracking, error handling for RateLimitError and APIConnectionError.
01
Network
Tell me the whole process of a search, from typing in the browser to getting the result.
+
Full journey:
1. Browser checks cache (memory → disk → OS)
2. DNS resolution: browser → OS resolver → ISP DNS → root nameserver → TLD → authoritative NS → returns IP
3. TCP 3-way handshake (SYN → SYN-ACK → ACK)
4. TLS handshake for HTTPS (certificate exchange, session keys)
5. HTTP request sent
6. Server: load balancer → web server → app server → cache → DB
7. Response travels back, browser parses HTML, fetches sub-resources
8. DOM → CSSOM → Render tree → Layout → Paint → Composite
01
API
What is REST and why is it stateless?
+
REST (Representational State Transfer) is an architectural style. Key constraints: stateless (each request contains all info needed — no server-side session), client-server separation, uniform interface (resource-based URLs, HTTP verbs), cacheable, layered system.

Statelessness enables: horizontal scaling (any server handles any request), reliability, simpler caching. Auth is via tokens (JWT) sent with each request.
02
API
Status codes — 200, 404, 500 and the important ones.
+
2xx: 200 OK, 201 Created, 204 No Content
3xx: 301 Moved Permanently, 304 Not Modified
4xx: 400 Bad Request, 401 Unauthorized (not authenticated), 403 Forbidden (authenticated but not allowed), 404 Not Found, 409 Conflict, 422 Unprocessable Entity (FastAPI validation)
5xx: 500 Internal Server Error, 502 Bad Gateway, 503 Unavailable

Key: 401 = "who are you?", 403 = "I know you, you can't do this."
03
API
API is slow — what do you do?
+
Diagnose first: add timing logs, check DB query plans (EXPLAIN ANALYZE), use APM (Sentry, Datadog).

Common fixes: N+1 queries → use joinedload; missing indexes → add them; slow external calls → cache or make async; sync code blocking event loop → switch to async httpx.AsyncClient; high traffic → add Redis caching + rate limiting.
04
API
What is serialization and how did you handle validation?
+
Serialization converts Python objects to JSON for HTTP transfer. In FastAPI, Pydantic models handle both directions — validate incoming JSON and serialize responses.

Validation: Pydantic defines schema with types and constraints (min_length, ge=0, regex). FastAPI validates automatically, returning 422 on failure. Custom validators via @field_validator. Business logic validation in the service layer, not the router.
01
Data Structures
What is the difference between a graph and a tree?
+
A tree is a connected, acyclic graph with a root node and parent-child hierarchy. A graph is a general structure — can have cycles, multiple components, and directionality. Every tree is a graph, not every graph is a tree. Trees for hierarchical data; graphs for networks.
02
Data Structures
Array vs Linked List. Dynamic Programming vs Greedy.
+
Array: contiguous memory, O(1) random access, O(n) insert/delete.
Linked List: scattered nodes with pointers, O(n) access, O(1) insert/delete at known node.

Greedy: locally optimal choice at each step. Fast, works when problem has greedy choice property.
DP: overlapping subproblems, memoize each. Guarantees global optimum. More expensive but correct where greedy fails.
03
Problem Solving
You have 1 million records and need to find duplicates efficiently.
+
Use a hash set: iterate once — if item in set it's a duplicate, else add it. O(n) time, O(n) space.

Alternatives: sort first O(n log n) then scan adjacent — O(1) extra space. In DB: GROUP BY + HAVING COUNT(*) > 1. For data beyond memory: hash partitioning.
01
Database
What is ACID compliance?
+
Atomicity: all-or-nothing — if one step fails, all roll back.
Consistency: DB moves from one valid state to another, all constraints respected.
Isolation: concurrent transactions behave as if sequential — no dirty reads.
Durability: committed transactions survive crashes (WAL).

PostgreSQL is fully ACID-compliant. Critical for healthcare and financial data.
02
Database
What are database indexes and when to use them?
+
Indexes (B-tree by default in PostgreSQL) allow O(log n) lookup instead of O(n) full table scan.

Add on: columns in WHERE, JOIN ON, ORDER BY, GROUP BY. Always index foreign keys.
Trade-offs: speed up reads, slow down writes, use extra disk space.
Check: EXPLAIN ANALYZE to verify index usage.
03
Database
What is a JOIN? How do you design a schema?
+
JOIN combines rows from tables on a related column. INNER JOIN = only matches. LEFT JOIN = all left + matching right. FULL OUTER JOIN = all rows from both.

Schema design: identify entities → attributes → relationships → normalize (3NF) → strategic denormalization → add constraints → plan indexes. Every table: id, created_at, updated_at. JSONB for flexible metadata. Alembic for migrations.
04
Database
Multi-threading, Deadlocks, and Aggregation.
+
Multi-threading: threads share process memory. Python GIL limits CPU parallelism — use asyncio for I/O-bound, multiprocessing for CPU-bound.

Deadlock: two transactions each hold a lock the other needs. PostgreSQL detects and kills one. Prevent by: consistent lock order, short transactions, SELECT FOR UPDATE SKIP LOCKED for queues.

Aggregation: COUNT, SUM, AVG, MAX, MIN with GROUP BY. Use HAVING to filter after aggregation.
05
SQL Challenge
Design a posts+comments schema like Twitter. Write a query for highest avg confidence score with min 50 predictions.
+
-- Schema
users(id, username, email, created_at)
posts(id, user_id FK, content, like_count, created_at)
comments(id, post_id FK, user_id FK, parent_comment_id FK, content, created_at)
likes(user_id FK, post_id FK, created_at)  -- composite PK

-- Query
SELECT category, AVG(confidence_score) AS avg_score
FROM predictions
GROUP BY category
HAVING COUNT(*) >= 50
ORDER BY avg_score DESC
LIMIT 1;
Key: HAVING filters after aggregation (vs WHERE before). Self-referencing parent_comment_id enables nested replies.
01
Python
list vs tuple. What are generators?
+
List ([]): mutable, can add/remove items.
Tuple (()): immutable, hashable, ~10-15% faster. Use for fixed data, dict keys, multi-return values.

Generators: functions that yield values lazily — only the current item in memory. Critical for large files, streaming, infinite sequences.
def large_range(n):
    i = 0
    while i < n:
        yield i; i += 1
Use (x*2 for x in range(1_000_000)) instead of a list when you don't need all values at once.
02
Python
Why is a mutable default argument dangerous? Explain decorators.
+
Mutable default: default args evaluate once at definition — a list default persists state across calls.
# WRONG
def append_to(item, lst=[]):
    lst.append(item); return lst
# CORRECT: use None as default, create inside
Decorator: a function that wraps another to add behavior without modifying it.
from functools import wraps
def timer(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        import time; start = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__}: {time.time()-start:.3f}s")
        return result
    return wrapper
FastAPI uses decorators for all route registration.
03
Python
What does SOLID stand for?
+
Single Responsibility — one class, one job.
Open/Closed — open for extension, closed for modification.
Liskov Substitution — subclasses replace parent without breaking behavior.
Interface Segregation — don't force unused interface implementations.
Dependency Inversion — depend on abstractions, not concrete implementations.

In FastAPI: DI via Depends() is literally the D in SOLID.
04
Python
How does Python run your code? What is a runtime error vs a syntax error?
+
How Python runs code: Python first parses your file and compiles it to bytecode (.pyc). Then the CPython interpreter executes that bytecode line by line — you don't compile manually, this is automatic.

Syntax error: caught at parse time, before any code runs.
if True  # SyntaxError: missing colon
Runtime error: code is syntactically valid but fails during execution.
name = None
print(name.upper())   # AttributeError at runtime
x = 1 / 0             # ZeroDivisionError at runtime
Key fact: Python is dynamically typed — type errors only surface at runtime, not before execution like in Java or TypeScript.
01
FastAPI
How does FastAPI work and how do you structure a project?
+
FastAPI is built on Starlette (async HTTP) + Pydantic (validation). Type hints drive automatic validation, serialization, and OpenAPI docs. Async routes run on the event loop; sync routes run in a thread pool.

app/
├── main.py           # include routers
├── core/config.py    # BaseSettings
├── routers/          # APIRouter per domain
├── schemas/          # Pydantic models
├── models/           # SQLAlchemy models
├── services/         # Business logic
├── db/session.py     # Engine + SessionLocal
└── tests/
02
FastAPI
What is dependency injection in FastAPI?
+
Depends() declares reusable dependencies injected into routes — DB sessions, auth, rate limiting.
async def get_db():
    db = SessionLocal()
    try: yield db
    finally: db.close()

async def get_current_user(
    token: str = Depends(oauth2_scheme),
    db: Session = Depends(get_db)
):
    return verify_token(token, db)

@app.get("/me")
async def read_me(user = Depends(get_current_user)):
    return user
Benefits: testable (swap real DB for test DB), composable, automatic cleanup with yield.
03
FastAPI
Sync vs async in FastAPI. Background tasks.
+
async: I/O-bound work (DB queries, HTTP calls). async def routes run on the event loop — never block with sync calls inside them (use run_in_executor).
sync: CPU-bound or existing sync libraries — FastAPI runs these in a thread pool automatically.

Background tasks:
@app.post("/notify")
async def notify(bg: BackgroundTasks, email: str):
    bg.add_task(send_email, email)
    return {"status": "queued"}
For heavy jobs (ML inference): Celery + Redis broker.
01
Testing
Example of a test you wrote. What's your testing strategy?
+
From Roof — testing auth endpoint:
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

def test_create_property_requires_auth():
    r = client.post("/v1/properties/", json={...})
    assert r.status_code == 401

def test_create_property_success(auth_headers):
    r = client.post("/v1/properties/",
        json={"title": "Test", "price": 1000},
        headers=auth_headers)
    assert r.status_code == 201
    assert r.json()["title"] == "Test"
Strategy: unit tests for services, integration tests with a test DB (transactions that roll back), API tests with TestClient. Mock external calls with respx.
01
OOP
Explain OOP principles. Inheritance vs composition.
+
Encapsulation: bundle data + methods, hide internals.
Inheritance: child class inherits from parent — "is-a" relationship.
Polymorphism: same interface, different implementations.
Abstraction: hide implementation, expose only the interface.

Inheritance vs Composition: Inheritance = "is-a" (Dog is-a Animal). Composition = "has-a" (Car has-a Engine). Rule: favor composition — more flexible, easier to test, avoids fragile hierarchies.
01
Docker
How do you Dockerize a FastAPI app?
+
Multi-stage build: python:3.11-slim base, copy requirements.txt first (layer caching), then app code. uvicorn as ASGI server. Secrets via env vars / Azure Key Vault, never baked in. Health check at /health. Non-root user, .dockerignore, pinned deps.
02
Docker
How does Docker layer caching benefit CI/CD?
+
Each Dockerfile instruction creates a cached layer. If two engineers share a base image and copy requirements.txt before app code, the dependency installation layer is cached — only changed app code rebuilds.

CI/CD benefit: builds go from 5 minutes to 30 seconds when only code changed. Requires: copy requirements.txt before source, same base image tag, push layer cache to registry (--cache-from in Docker Buildx).
01
Behavioral
Tell me about yourself.
+
"I'm a Full-Stack Developer specializing in Python backend — FastAPI, PostgreSQL, RESTful APIs. At Buguard I built APIs for security workflows. Before that I built Roof — 40+ FastAPI endpoints, JWT auth, RBAC, PostgreSQL + SQLAlchemy, Elasticsearch. What makes me different: I build frontends too, so I design APIs from both sides of the contract. I'm looking for a role where I can go deeper on backend architecture."
02
Behavioral
Tell me about a project. Biggest challenge? How do you debug?
+
Roof: "40+ endpoints, JWT + RBAC, PostgreSQL + Elasticsearch. Hardest part: RBAC design — different users (owner, agent, seeker) needed different access everywhere. Solved with a composable FastAPI dependency chain. Building the frontend meant API contracts were cleaner."

Debug process: reproduce first → isolate → read full stack trace → check logs + recent changes → form hypothesis → fix → add regression test. Tools: breakpoint(), DB query logging, EXPLAIN ANALYZE.
03
Behavioral
How do engineers collaborate with product/design?
+
"I join design reviews early — before any code — to flag technical constraints before they become expensive. I translate designs to API contracts and review with product first. I ask 'why' about requirements, not just 'what', so I can sometimes suggest a simpler solution that achieves the same goal."

Frontend SWE

JavaScript · TypeScript · React/Vue · State Management · Performance · Testing · Version Control · Behavioral

01
JavaScript
Difference between sync and async in JavaScript.
+
Synchronous: code executes line by line, blocking — each operation waits for the previous one.
Asynchronous: non-blocking — operations (API calls, timers, I/O) are dispatched and a callback/promise handles the result when ready, while other code continues.

Mechanisms: callbacks (old) → Promises (.then/.catch) → async/await (modern sugar over Promises). The event loop processes async results from the callback queue when the call stack is empty.
02
JavaScript
What's a closure? What is hoisting?
+
Closure: a function that remembers its outer scope after the outer function returns.
function makeCounter() {
  let count = 0;
  return () => ++count;
}
const counter = makeCounter();
counter(); // 1, counter(); // 2
Hoisting: declarations move to the top of scope at compile time. var initializes as undefined. function declarations are fully hoisted. let/const are hoisted but not initialized (temporal dead zone — accessing before declaration throws ReferenceError).
03
JavaScript
Event delegation. Local Storage vs Session Storage.
+
Event delegation: attach one handler to a parent instead of many to children. Works for dynamically added elements via event bubbling.
document.querySelector('.list').addEventListener('click', e => {
  if (e.target.matches('.item')) { /* handle */ }
});
localStorage: persists until cleared, ~5-10MB, all tabs.
sessionStorage: cleared on tab close, per tab.

Never store tokens in either (XSS vulnerability) — use httpOnly cookies.
01
TypeScript
Why TypeScript over JavaScript? Key features you use.
+
TypeScript adds static typing — catches type errors at compile time, not runtime. Key features in practice: interface/type for API response shapes, generics for reusable components/services, enums for constants, strict mode to catch nullability bugs, and typed Axios service layers.

At Mahjoz: typed 75+ API integrations with Axios — catching shape mismatches at compile time saved hours of debugging. Pinia stores typed with generic state shapes.
02
TypeScript
Interface vs type alias. Generics example.
+
interface: extendable, declarative merging (two declarations merge), best for object shapes.
type: can represent unions, tuples, primitives — more flexible.
// Interface (preferred for API shapes)
interface User { id: number; name: string; }
interface Admin extends User { role: 'admin'; }

// Generic utility
type ApiResponse<T> = { data: T; error: string | null; meta: { page: number } };
const res: ApiResponse<User[]> = await fetchUsers();
01
Vue 3
Vue 3 Composition API — why use it over Options API?
+
Composition API groups logic by feature instead of by option type (data/methods/computed). Advantages: better TypeScript support, logic reuse via composables (vs mixins), co-locate related code, smaller bundle with tree-shaking.

At Mahjoz: 56 Pinia stores + complex booking state would be unmaintainable with Options API. Composition API + <script setup> + typed Pinia made each module self-contained.
02
Vue 3
How did you handle RTL/LTR bilingual support?
+
At Mahjoz (Arabic/English): set dir="rtl"/"ltr" on <html> based on active locale. CSS logical properties (margin-inline-start instead of margin-left) for layout that flips automatically. i18n with vue-i18n — all strings in ar.json/en.json. RTL-aware Tailwind classes where needed. Tested by switching locale in dev and checking all 43 modules for layout breaks.
03
React
Key React hooks and when to use each.
+
useState: local component state.
useEffect: side effects (data fetching, subscriptions, DOM manipulation). Cleanup function prevents memory leaks.
useCallback: memoize functions to prevent child re-renders.
useMemo: memoize expensive computations.
useRef: persist values without re-rendering, access DOM nodes.
useContext: consume context without prop drilling.

Rule: don't over-memoize — useCallback/useMemo have overhead too. Profile first.
01
State Management
How did you manage complex state at Mahjoz with Pinia?
+
56 Pinia stores — one per feature domain (bookings, orders, notifications, auth, etc.). Each store: state typed with TypeScript interfaces, actions for async operations (API calls), getters for derived state.

Key patterns: normalized state (IDs as keys, not arrays) for O(1) lookup, optimistic updates for UI responsiveness, WebSocket events dispatched directly to relevant store actions. Stores composed (a booking store could import from a user store) — Pinia allows this cleanly unlike Vuex.
02
State Management
React Query vs manual fetch — when and why?
+
React Query handles the full async data lifecycle: caching, background refetching, loading/error states, pagination, optimistic updates, and deduplication of concurrent requests.

Manual fetch: fine for fire-and-forget mutations or one-off calls. React Query: any server state you display — it eliminates 80% of useEffect(fetch) boilerplate and makes stale-while-revalidate trivial.

Rule: if you're storing API response in useState, you probably want React Query.
01
Performance
How do you optimize a slow frontend? What's code splitting?
+
Diagnose first: Chrome DevTools Performance tab, Lighthouse audit, Network tab for bundle sizes.

Common fixes: code splitting (lazy-load routes/components), image optimization (WebP, lazy loading, proper dimensions), virtual scrolling for long lists, memoization for expensive renders, reduce re-renders (track with React DevTools), move large dependencies to CDN, eliminate unused CSS.

Code splitting: split the JS bundle so users only download what they need. In Vue: defineAsyncComponent(() => import('./Heavy.vue')). In React: React.lazy() + Suspense.
01
Version Control
What's the point of a Pull Request? What's your Git workflow?
+
PR purpose: code review, CI/CD gates, discussion, documentation, audit trail. Good PR: small focused change, clear description, link to issue, tests included, self-review before requesting.

Git workflow (feature branch): main is always deployable → create feature/my-feature → commit with conventional commits (feat:, fix:, chore:) → open PR → review + fix → squash merge → delete branch. At Mahjoz: 43 modules meant branch naming convention was critical to avoid confusion.
01
Behavioral
Tell me about a complex frontend challenge you solved.
+
Use Mahjoz: "The booking module had real-time state — WebSocket updates, optimistic mutations, and 8+ filter states that all had to stay in sync. I designed a Pinia store with normalized state (IDs as keys), WebSocket listeners that dispatched directly to store actions, and optimistic updates that rolled back on API error. It went from a confusing tangled component to a predictable, testable data flow."
02
Behavioral
What kind of AI features are you building? Do you use FastAPI or Django?
+
AI features: integrating LLM APIs (OpenAI, Anthropic) for text processing, building endpoints that stream AI responses to the frontend, structuring prompts for consistent structured outputs, and logging/monitoring AI calls with correlation IDs.

FastAPI vs Django: "FastAPI for new APIs — async, fast, auto-docs. Django when a project needs admin panel or inherits existing Django ORM. On Roof I chose FastAPI because of the async requirements and AI API integrations."

UI Developer

HTML · CSS · JavaScript Basics · jQuery · Responsive Design · Accessibility · Behavioral

01
HTML
Difference between <div> and <span>. Explain semantic HTML.
+
<div> = block-level (full width, new line). <span> = inline (content-width, stays in flow).

Semantic HTML uses elements that describe their meaning: <header>, <nav>, <main>, <article>, <section>, <aside>, <footer>, <figure>, <time>. Benefits: accessibility (screen readers), SEO, readability. Anti-pattern: <div class="header"> when you mean <header>.
01
CSS
CSS Box Model. How does flexbox work?
+
Box Model (inside out): content → padding → border → margin. box-sizing: border-box includes padding + border in width/height (what you usually want).

Flexbox: 1D layout. Container: display: flex, flex-direction, justify-content (main axis), align-items (cross axis), gap. Children: flex: 1 (grow), align-self. For 2D use CSS Grid.
02
CSS
Center a div vertically and horizontally. inline vs block vs inline-block.
+
/* Flexbox */
.parent { display: flex; justify-content: center; align-items: center; }
/* Grid */
.parent { display: grid; place-items: center; }
/* Absolute */
.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); }
block: full width, new line, all box model properties work.
inline: content-width, no new line, ignores width/height/vertical margin.
inline-block: flows inline, but respects all box model properties — good for buttons, badges.
01
JavaScript
let vs var vs const. == vs ===.
+
var: function-scoped, hoisted as undefined, can re-declare. Avoid.
let: block-scoped, can reassign, temporal dead zone.
const: block-scoped, must initialize, cannot reassign. Default choice.

== coerces types: 0 == "0" → true. === strict, no coercion: 0 === "0" → false. Always use ===.
01
jQuery
Why jQuery in 2025? Core patterns.
+
Honest answer: for new projects you wouldn't. But it exists in legacy codebases (WordPress, enterprise). At Vodafone/Advansys: likely maintaining jQuery-heavy existing systems.

Core patterns:
$('#id')  // select by id
$('.cls').toggleClass('active');
$('#btn').on('click', fn);
$.ajax({ url: '/api', method: 'GET', success: cb });
$(document).on('click', '.dynamic-item', fn); // delegation
$(document).ready() = DOM parsed, images may not be loaded. window.onload = everything loaded including images.
01
Responsive
How do you ensure responsive design? Translate Figma to code?
+
Responsive: mobile-first CSS (min-width media queries), fluid layouts (%, fr), clamp() for fluid typography, responsive images (srcset, picture), touch targets min 44×44px, real device testing.

Figma to code: extract design tokens first (colors, spacing, typography) as CSS variables. Build bottom-up (atoms → components). Use Dev Mode for exact values. Clarify hover/focus/error states early — they're often missing from Figma.
01
Accessibility
How do you meet WCAG standards?
+
WCAG 2.1 AA is the common target: color contrast 4.5:1 (normal text), keyboard navigation throughout, visible focus indicators, semantic HTML, ARIA labels where HTML isn't enough, aria-live for dynamic content, alt text on images, <label> for every input, form errors via aria-describedby.

Test with: axe browser extension, keyboard-only navigation, VoiceOver/NVDA screen reader.
01
Behavioral
Why Vodafone/Advansys? Tight deadline project. Group disagreement on design.
+
Why Vodafone/Advansys: scale (millions of users — UI decisions have real impact), the challenge of modernizing legacy UIs without disrupting existing users, national-scale product impact.

Tight deadline: scope down intelligently, not just work faster. Communicate risks early. Ship something working then iterate.

Group disagreement: reframe from opinions to criteria — "Does this meet the user's needs?" Bring data (analytics, usability tests). Propose A/B testing when genuinely uncertain.

UI/UX Design

Usability & Accessibility · Tools & Techniques · Behavioural · Advanced · Senior Role

01
Usability
What makes a UI/UX design accessible? Common usability principles?
+
Accessible design: 4.5:1 color contrast, keyboard-navigable, screen reader support (semantic HTML, ARIA), focus indicators, alt text, captions for video, 16px+ body text, 44×44px touch targets, never use color alone to convey meaning.

Usability principles (Nielsen's 10): visibility of system status, match real-world conventions, user control and freedom, consistency, error prevention, recognition over recall, flexibility for novice/expert, aesthetic minimalism, error recovery, help & documentation.
02
Usability
What are heuristic principles in UX design?
+
Heuristic evaluation uses established principles (Nielsen's 10) to find usability issues without user testing. Evaluators independently assess the UI against each heuristic, rate severity (0–4), compile findings.

Process: gather evaluators (3–5 ideal), evaluate independently, consolidate, prioritize by severity × frequency. Good for early reviews and design audits of existing products.
01
Tools
A/B testing. Microinteractions.
+
A/B testing: show two versions to different user segments, measure on defined metric (conversion, click-through). Process: hypothesis → success metric → split traffic → statistical significance → implement winner. Test one variable at a time.

Microinteractions: small moments of feedback — button press, loading spinner, toggle switch, form validation. 4 parts (Saffer): trigger → rules → feedback → loops/modes. Done well: invisible but missed when absent.
01
Behavioral
Challenging project. Design critiques. Prioritization. User-centered design.
+
Design critique: separate work from self. Listen fully. Ask "why" before responding. Distinguish taste (push back with rationale) from usability issues (act on them).

Prioritization: impact vs effort matrix. Prioritize flows blocking core tasks. Use data: where do users drop off?

User-centered: research first (interviews, analytics, heatmaps), test prototypes with 5 real users (catches 85% of issues — Nielsen), iterate on findings not opinions. In constrained environments: guerrilla testing, support ticket analysis.
01
Advanced
Material Design vs HIG. Cognitive psychology in UX. Information Architecture.
+
Material Design (Google): elevation/shadows, bold colors, cross-platform. HIG (Apple): feels native to iOS/macOS, translucency, system fonts, strong navigation patterns. Follow HIG for iOS apps.

Cognitive psychology: working memory limits (7±2 chunks) → progressive disclosure. Mental models → match UI to real-world metaphors. Gestalt (proximity, similarity, closure) → how users group elements.

Information Architecture: how content is organized so users can find it. Methods: card sorting, tree testing, user flows, sitemaps. Good IA is invisible.
01
Senior
Progressive disclosure. Designing for novice and expert users. Conflicting stakeholder feedback.
+
Progressive disclosure: show only what's needed at each step, reveal complexity gradually. Reduces cognitive overload for new users, allows experts to go deeper. Examples: Gmail's "More options", iOS Settings advanced section.

Novice + expert: simple default path + discoverable power features. Keyboard shortcuts + tooltips, "simple mode" toggle, defaults that work for 80% + customization for the rest.

Conflicting stakeholders: bring evidence over opinions. Map feedback to business goals. Use rapid prototyping + testing to resolve "we don't know" disagreements. Document decisions to prevent them resurfacing.

ML / Data Science

Pipelines & Data Leakage · Pandas · NLP

01
Pipeline
In train.py you use Pipeline. What problem does it solve, and what is data leakage?
+
sklearn Pipeline chains preprocessing + model into one object: reproducibility, prevents data leakage, simplifies cross-validation, enables pipeline.predict() on raw data.

Data leakage: information from test set (future data) influences training → inflated metrics that don't generalize. Classic mistake: fit scaler on entire dataset before splitting → test statistics contaminate training.

Pipeline fixes this: fit only on training data, transform consistently using training statistics.
01
Pandas
Difference between .loc and .iloc in Pandas.
+
.loc: label-based — select by index label or column name. df.loc[2, 'name'] = row with label 2.
.iloc: integer position-based. df.iloc[2, 0] = always 3rd row, 1st column.

Common gotcha: if index is 0,1,2... they look the same. After filtering/resetting, indices may not match positions — that's when the distinction matters.
01
NLP
Top 3 most common words from AG News dataset excluding stopwords.
+
from collections import Counter
from nltk.corpus import stopwords
import nltk; nltk.download('stopwords')

stop_words = set(stopwords.words('english'))
all_words = ' '.join(df['text']).lower().split()
filtered = [w for w in all_words if w.isalpha() and w not in stop_words]
top_3 = Counter(filtered).most_common(3)
For scale (1M+ rows): use CountVectorizer from sklearn or process in chunks. Add lemmatization for cleaner results.
02
NLP
What is TF-IDF? Naive Bayes vs Logistic Regression for text classification.
+
TF-IDF = Term Frequency × Inverse Document Frequency. TF: how often a word appears in a doc. IDF: penalizes words appearing in many docs. Result: words important to one doc but rare across all docs score highest.

Naive Bayes: generative, assumes feature independence. Fast, works well with small data and high-dimensional sparse features.
Logistic Regression: discriminative, better accuracy with more data, handles correlated features, more interpretable.

Practice: NB is a great baseline; LR usually wins with sufficient data.

Django

Settings · Views & Endpoints · ORM · Django REST Framework

01
Settings
What is ALLOWED_HOSTS in settings.py? Write the syntax.
+
A list of hostnames your Django app is allowed to serve. Requests from any host not in the list get a 400 error. This protects against HTTP Host header attacks.
# settings.py
ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'mysite.com']

# All hosts — never use in production
ALLOWED_HOSTS = ['*']
When DEBUG = False, ALLOWED_HOSTS must be set. When DEBUG = True, Django ignores it (localhost always works).
02
Settings
What does DEBUG = True vs DEBUG = False do?
+
# settings.py
DEBUG = True   # development
DEBUG = False  # production
DEBUG = True: Django shows a detailed error page with full stack trace, local variables, and request info. Static files are served by Django automatically.

DEBUG = False: No error details exposed to users (generic 500 page). ALLOWED_HOSTS must be set. Django does NOT serve static files — you need WhiteNoise, nginx, or a CDN.

Rule: always False in production. Never commit True to a live server.
01
Views
What are the different ways to create an API endpoint in Django?
+
Three main approaches in DRF:

1. Function-Based View (FBV) — use @api_view decorator:
@api_view(['GET', 'POST'])
def book_list(request):
    if request.method == 'GET':
        books = Book.objects.all()
        return Response(BookSerializer(books, many=True).data)
2. Class-Based View (CBV) — extend APIView:
class BookList(APIView):
    def get(self, request):
        books = Book.objects.all()
        return Response(BookSerializer(books, many=True).data)
3. ModelViewSet + Router — auto-generates all CRUD URLs:
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

router = DefaultRouter()
router.register('books', BookViewSet)
urlpatterns += router.urls
02
Views
What is the difference between function-based views and class-based views?
+
Function-Based View (FBV): a plain function decorated with @api_view. You handle each HTTP method with if/else. Simple to read, easy to debug, good for custom logic.

Class-Based View (CBV): a class where each method name matches the HTTP verb (get, post, put, delete). Less if/else, more organized for standard CRUD. DRF generic views (ListCreateAPIView, RetrieveUpdateDestroyAPIView) let you write almost no code:
class BookDetail(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
Rule: FBV for custom logic. CBV for standard CRUD — less repetition.
03
Views
What is the difference between a query parameter and a request body? When do you prefer the body?
+
Query parameter: appended to the URL after ?. Visible in the URL, can be bookmarked, used for filtering or pagination on GET requests.
GET /books/?genre=fiction&page=2
request.query_params.get('genre')  # access in DRF
Request body (form data / JSON): sent inside the HTTP request body, not visible in the URL. Used when creating or updating a resource (POST, PUT, PATCH).
POST /books/
Body: {"title": "1984", "author_id": 5}
request.data.get('title')  # access in DRF
When to prefer the body: any time you're sending data to create or update something, or when the data is sensitive (password, payment info), large, or complex (nested objects). Never put sensitive data in query params — they end up in server logs and browser history.
01
ORM
Write the syntax for a ForeignKey (one-to-many) and a ManyToManyField in Django models.
+
class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=200)

    # One-to-many: many books → one author
    author = models.ForeignKey(
        Author,
        on_delete=models.CASCADE,
        related_name='books'
    )

    # Many-to-many: a book can have many genres
    genres = models.ManyToManyField('Genre', blank=True)

class Genre(models.Model):
    name = models.CharField(max_length=50)
Access:
book.author           # the author object
author.books.all()    # all books by this author
book.genres.all()     # all genres of this book
book.genres.add(genre_obj)  # add a genre
02
ORM
What is the difference between .get() and .filter()?
+
# .get() — returns one object or raises an exception
book = Book.objects.get(id=1)
# Raises DoesNotExist if not found
# Raises MultipleObjectsReturned if more than one match

# .filter() — returns a QuerySet (empty, one, or many)
books = Book.objects.filter(genre='fiction')  # QuerySet
book = Book.objects.filter(id=1).first()      # safe single fetch
Rule: use .get() only when you're certain exactly one record exists (e.g., by primary key or unique field). Use .filter() for anything else — it never raises an exception for zero or many results.
03
ORM
What does get_or_create() do? Write the syntax.
+
Returns the existing object if found, or creates it if not. Always returns a tuple: (object, created) where created is a boolean.
author, created = Author.objects.get_or_create(
    name='George Orwell',           # lookup field
    defaults={'bio': 'British novelist'}  # only used when creating
)

if created:
    print("New author added")
else:
    print("Author already existed")
defaults are only applied on creation, not used in the lookup. This is a single atomic database query — safer than doing .get() then .create() separately, which could fail under concurrent requests.
01
DRF
What is Django REST Framework and when would you use it over FastAPI?
+
DRF is batteries-included: Serializers, ViewSets, Routers, browsable API, Token/JWT auth, permissions system. Built on top of Django so you get the admin panel and ORM for free.

Use DRF when: you're already on Django, need the admin panel, or building standard CRUD with minimal setup.
Use FastAPI when: you need async performance, building microservices or AI/ML APIs, or starting a new project where speed matters.

Short answer: "DRF for projects that benefit from Django's ecosystem. FastAPI for new async APIs — like Roof, where I needed async endpoints and AI integrations."
02
DRF
How do you set up JWT authentication in DRF?
+
# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

# urls.py
urlpatterns = [
    path('api/token/', TokenObtainPairView.as_view()),
    path('api/token/refresh/', TokenRefreshView.as_view()),
]
POST credentials to /api/token/ → get access + refresh tokens. Send Authorization: Bearer <token> on protected routes. Install: pip install djangorestframework-simplejwt.
03
DRF
What is a ModelViewSet? What endpoints does it generate automatically?
+
A ModelViewSet combines all CRUD actions into one class. Register it with a Router and it auto-creates all URLs.
# views.py
class BookViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# urls.py
router = DefaultRouter()
router.register('books', BookViewSet)
urlpatterns += router.urls
Auto-generated routes:
  • GET /books/ — list all
  • POST /books/ — create
  • GET /books/{id}/ — retrieve one
  • PUT /books/{id}/ — full update
  • PATCH /books/{id}/ — partial update
  • DELETE /books/{id}/ — delete
You can restrict actions: http_method_names = ['get', 'post'] or use ReadOnlyModelViewSet.
04
DRF
What is the difference between Serializer and ModelSerializer?
+
Both convert between Python objects and JSON. ModelSerializer auto-generates fields from a model.

Serializer — define all fields manually, also define create() and update() yourself:
class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=200)

    def create(self, validated_data):
        return Book.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.save()
        return instance
ModelSerializer — auto-generates fields and create()/update() from the model:
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'author']
        # or: fields = '__all__'
Use ModelSerializer for standard model CRUD. Use plain Serializer for non-model data (like a login form) or complex custom logic.
05
DRF
How do you receive an image from a user and save it?
+
# models.py
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar = models.ImageField(upload_to='avatars/')

# serializers.py
class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ['avatar']

# views.py
class ProfileView(APIView):
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request):
        serializer = ProfileSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(user=request.user)
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)
Also needed in settings.py:
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
And in urls.py for development:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Install Pillow — Django's ImageField requires it: pip install Pillow.
Frontend: send as multipart/form-data, not JSON.

Full-Stack

Architecture · Design Principles

01
Architecture
What is event-driven architecture?
+
A pattern where components communicate by producing and consuming events instead of calling each other directly. A producer emits an event ("order placed"), and consumers react to it independently.

Three parts:
  • Producer — emits events (an API endpoint, a webhook, a user action)
  • Event broker — routes events (Kafka, RabbitMQ, Redis pub/sub, Celery)
  • Consumer — listens and processes events (background worker, another service)
Example with Celery (Django):
# Producer — Django view
@api_view(['POST'])
def register(request):
    user = User.objects.create(**request.data)
    send_welcome_email.delay(user.id)  # emit event
    return Response({'id': user.id}, status=201)

# Consumer — Celery task
@shared_task
def send_welcome_email(user_id):
    user = User.objects.get(id=user_id)
    # send the email
Why use it: the register endpoint doesn't wait for the email to send (faster response). The email worker is decoupled — you can replace or scale it without touching the view.
01
Design
What is modularity in software development?
+
Modularity means splitting your code into separate, self-contained units where each one handles one responsibility. A module has a clear interface and hides its internal details.

In Django — each app is a module:
myproject/
├── users/         ← handles auth, profiles
├── orders/        ← handles orders
├── payments/      ← handles payments
└── notifications/ ← handles emails, push
Each Django app has its own models.py, views.py, urls.py, and serializers.py. Apps communicate through imports or events — they don't reach into each other's internals.

Benefits:
  • Easy to understand one module without reading the whole codebase
  • Easy to test each module in isolation
  • Teams can work on different modules at the same time
  • You can replace or remove one module without breaking others
In code: functions do one thing, classes group related behavior, and you import only what you need.