Company A — Junior Strong / Middle Python Developer — prep map
Checklist format: tick what you can explain and defend under questioning, not what you have used. Bold is the primary note; the rest add depth.
Priority: 🔴 core (in the ad, will be probed) · 🟡 important (in the ad, lighter) · 🟢 breadth (implied)
The ad, decoded
| Requirement | What they will actually probe | Weight |
|---|---|---|
Python fundamentals, typing, async/await |
data model questions, a typed function, an event-loop mistake | 🔴 |
| WebSockets and real-time (streaming data or audio) | design a persistent-connection service; backpressure; reconnection | 🔴 |
| FastAPI / Flask / Django | FastAPI in depth: DI, async, WebSocket endpoint, testing | 🔴 |
| Audio processing and streaming (capture, convert, transmit; transcription) | sample rates, PCM bytes, chunking, ffmpeg, an STT pipeline | 🔴 |
| LLM APIs, in particular Claude (prompt design, structured outputs, tool calling) | the Messages API shape, the tool loop, JSON that validates | 🔴 |
| PostgreSQL / MySQL, SQLAlchemy, efficient SQL, data modeling | N+1, indexes, EXPLAIN, session lifecycle, normalisation |
🔴 |
| Code quality, Google-style docstrings, data profiling | linters/formatters, what a docstring must say, profiling a new dataset | 🟡 |
| Data processing pipelines (plus) | pandas, idempotent steps, a queue | 🟡 |
| Docker basics | image vs container, layers, compose, multi-stage | 🟡 |
| Quick learner, adaptable; English | behavioural stories; the whole call is in English | 🟡 |
The product this ad describes: a real-time voice/transcription service — audio in over a WebSocket, a speech pipeline, Claude in the middle, results back over the same connection, everything stored in Postgres. Prepare the whole system end to end (section “The design question”, below), not just the parts.
🔴 Python fundamentals
- Mutable vs immutable, references, copies — the
def f(x=[])familyMutable vs immutableArgument passingShallow vs deep copyMutable default arguments - Classes,
self, class vs instance attributes,@classmethod/@staticmethodClasses in Pythonstaticmethod vs classmethodClass var vs instance varMagic methods -
__eq__/__hash__,isvs==, dict keys__eq__vs__hash__isvs==Hashable objects as keys - Generators and iterators;
yield; exhaustionIterators and generatorsGenerator exhaustionitertools - Decorators, context managers,
contextlibDecorators and context managerscontextlibfunctools.wrapsDecorator with arguments - Exceptions —
try/except/else/finally, custom hierarchies, chainingtry / exceptException swallowing infinally - Imports, modules, packages, circular importsImports and the module systemCircular imports
- dataclasses vs Pydantic;
*args / **kwargs; scopedataclassesdataclass vs attrs vs Pydantic*argsand**kwargsVariable scope - The GIL and memory model — enough to answer “threads or async”The GILMemory model and GC
- Tricky questions sweep — read the folder once, they ask these verbatimTricky questionsLate-binding closuresTruthinessDict mutation during iteration
🔴 typing
-
Optional,Union,Callable,list[str]vsList— the basics, fluentlyOptional, Union, Callable -
TypeVar, generics, PEP 695class Box[T]TypeVar and generics -
Protocolvs ABC — structural typing, and when a base class is wrongProtocol and structural typingProtocols and interfaces -
TypedDict,Literal,Final,Annotated,TypeGuardTypedDict, Literal, FinalAnnotated and TypeGuard - mypy / pyright in CI; what “strict” costsmypy and pyright strictnessType-checking strategyType-driven development
🔴 async / await
- Coroutines, the event loop,
await, tasks — what actually runs whenAsync Python and coroutinesEvent loop internalsasync defreturns a coroutine - Blocking the loop — the bug behind most “async is slow” storiesBlocking in async
run_in_executor/to_threadasyncio vs threads -
TaskGroup,gather, cancellation, timeoutsTaskGroup and structured concurrencyCancellation, timeouts, errors -
asyncio.Queue, backpressure, producer/consumer — the audio pipeline’s spineasyncio.Queue vs threading.QueueSynchronization primitivesCPU vs I/O tasks - Async in FastAPI —
defvsasync defroutes, the threadpoolFastAPI async and performancerun_in_threadpoolFastAPI async
🔴 WebSockets and real-time communication
- The protocol — handshake, frames (text vs binary), close codes, ping/pongWebSocket protocolWebSocket vs SSE vs long-pollServer-Sent Events
- Python implementation —
websockets, FastAPI endpoint, Django ChannelsPython implementationAsync Django and Channels - Connection management — heartbeats, timeouts, reconnection, backpressure, graceful shutdownConnection management
- Auth and security on a socket — token at the handshake, origin checksAuthenticationSecurity
- Scaling — sticky sessions, broker fan-out, one process per connectionScalingSocket.IOnginx WebSocket proxying
- Audio over the socket — control JSON + binary frames, reader/queue/consumer, barge-inStreaming audio over WebSocketsWebRTC and WebTransportTCP vs UDP
🔴 Audio processing and streaming
- PCM: sample rate, bit depth, channels; the byte arithmetic — 20 ms at 16 kHz mono int16 = 640 bytesAudio fundamentals for backends
- The three bugs — rate mismatch, layout mismatch, odd-length chunks (remainder buffer)Audio fundamentals for backends(§ The three bugs)
- Codecs vs containers — WAV, Opus/WebM, μ-law telephony, MP3; ffmpeg over pipes; resamplingAudio fundamentals for backends(§ Containers and codecs, § Converting)
- Capture — browser
MediaRecordervsAudioWorklet, telephony media streams,sounddeviceStreaming audio over WebSockets(§ Where the browser makes it hard) - STT and TTS — streaming vs batch, interim vs final, WER and why it misleads, time to first byteSpeech: STT and TTSVoice platforms
- VAD, endpointing, turn detection, barge-in; the latency budgetRealtime voice agents
Have the numbers ready: 16 kHz mono int16 = 32 KB/s; a 20 ms frame is 320 samples / 640 bytes; telephony is 8 kHz μ-law at 8 KB/s; base64 adds a third. Say them without looking and the “audio experience” line is covered.
🔴 Claude API — prompt design, structured outputs, tool calling
- The Messages API shape —
systemvsmessages, content blocks,stop_reason, stateless historyThe Claude Messages API in practiceThe chat API - The tool loop —
tool_use→ run →tool_resultbytool_use_id; all parallel results in one message;is_errorThe Claude Messages API in practice(§ Tool use)Function calling and structured outputThe agent loop - Structured outputs —
messages.parse/output_config.format; shape is guaranteed, truth is not; Pydantic afterFunction calling and structured outputLLM JSON validationPydantic in practice - Prompt design — stable-first ordering, tagged inputs, examples, no prefill, thinking and effortPrompt engineeringPrompt optimizationContext windows
- Streaming, caching, retries, batches — the production habitsThe Claude Messages API in practice(§ Streaming, § Prompt caching, § Errors)Provider abstraction and resilienceLLM gateway and caching
- Injection and output validation — the user’s audio transcript is untrusted inputPrompt injectionGuardrails and output validationHallucinations and tools
- Evaluating an LLM feature — a small eval set beats opinionsBuilding eval setsWhy LLM eval is hard
🔴 Web frameworks — FastAPI first
- FastAPI end to end — routing, Pydantic models, dependencies, middleware, exceptionsFastAPI overviewDependencies and injectionPydantic modelsMiddlewareException handling
- Project structure, background work, external clientsProject structureBackground tasks vs CeleryExternal API client
- Testing FastAPI, including WebSocket endpointsFastAPI testingpytest-asyncioMocking external APIs
- Auth, OpenAPI, deploymentSecurity and authenticationOpenAPI and docsDeploymentWSGI vs ASGI
- Flask and Django — enough to compare; the ORM and Channels if Django comes upFlaskDjango vs DRFDjango ORM guide
select_relatedvsprefetch_related - REST hygiene — status codes, idempotency, versioning, paginationREST principlesIdempotencyStatus codesVersioning and pagination
🔴 Relational databases, SQLAlchemy, SQL, data modeling
- SQL fundamentals, joins, transactions, isolationSQL fundamentalsTransactionsIsolation levelsWindow functions and CTEs
- Efficient queries — indexes,
EXPLAIN ANALYZE, why the index is not used, N+1IndexesEXPLAIN ANALYZEWhy your index is not usedN+1Index types - Data modeling — keys, relations, normalisation, when to denormaliseRelations and keysSQL vs NoSQLSharding and partitioning
- SQLAlchemy 2.0 — Core vs ORM, session lifecycle, loading strategies, asyncSQLAlchemyCore vs ORMSession lifecycleLoading strategies and N+1Async SQLAlchemyCommon pitfalls
- Migrations and pooling — Alembic, zero-downtime changes, connection poolsAlembicZero-downtime migrationsConnection pooling
- PostgreSQL vs MySQL — the differences that matter in an answerMySQLIsolation anomalies across DBspgvector in production
🟡 Code quality, documentation, data profiling
- Formatters, linters, pre-commit, reviewFormattersLintersPre-commit and review
- Google-style docstrings — what a docstring must say, and docstrings as tool schemasDocstrings and documentation
- Refactoring, tech debt, complexityRefactoringTech debt and complexitySOLID
- Data profiling — nulls, cardinality, distributions, duplicates, freshness; then checksData profiling and validation
- Testing — pytest fixtures, parametrize, mocks, property testspytest conceptsFixturesMock vs MagicMock vs patchTest pyramid
🟡 Data processing pipelines
- pandas, and when it breakspandas fundamentalsgroupby, merge, reshapeWhen pandas breaksPolars
- Pipeline design — idempotent steps, incremental loads, quality checks in the runETL orchestration and dbtParquet
- Queues for the slow parts — Celery, retries, idempotency, dead lettersWhat is CeleryRetriesIdempotencyBroker comparison
🟡 Docker
- Image vs container, layers, multi-stage builds, compose, volumes, networksDockerImage vs containerImage layersMulti-stage buildsComposeVolumes
- A Python service in a container — Uvicorn workers, env config, health checksFastAPI deploymentCI/CD basicsGitHub Actions
The design question to rehearse
“Design a service that transcribes a live call and answers questions about it.” Walk it in this order, and link each step to a note you have read:
- Client captures audio → binary frames over a WebSocket with a
startmessage declaring rate and encoding — Streaming audio over WebSockets. - Server: reader task → bounded
asyncio.Queue→ STT stream task; partial/final transcripts back as JSON — asyncio.Queue, Connection management. - Audio hygiene: 16 kHz mono int16, remainder buffer, VAD gating — Audio fundamentals.
- Finals go to Claude with a stable system prompt, structured output for the answer, tool calls for lookups — Claude Messages API.
- Persist transcripts and answers in Postgres via SQLAlchemy async sessions; index by call and time — Async SQLAlchemy, Indexes.
- Ship it: Docker image, one process per connection, sticky sessions, metrics — Scaling, Deployment.
Then name the failure modes unprompted: slow work in the reader, unbounded buffers, interim transcripts stored as final, a date in the system prompt killing the cache, N+1 when listing calls.
Behavioural — the Company A values as stories
| Value | Story to have ready | Notes |
|---|---|---|
| Growth | how you learned a new stack fast and what you did on day one | Approaching new technologies · How do you work with AI |
| Teamwork | a disagreement resolved with data, a review that improved the code | Disagreement with the team · Mentoring and feedback |
| Ownership | a mistake you owned, and the process change after it | A failed project or mistake · Handling not knowing |
| Openness | ambiguous requirements you clarified before building | Ambiguity and unclear requirements · Working with clients |
| Results | a result with a number in it | Strongest project · Most challenging part |
- The story structure and the six signals — every answer as context → options → decision → trade-off → resultThe six signalsJoining an existing projectWorking independently
- Questions to ask them, and the red flagsClosing questions and red flags
English: the whole call is in English. Rehearse the design walk-through above aloud, in English, twice — the ad’s English-level line is scored on exactly that.