Stage 01 of 09Start here

Foundations

The engineering bedrock under every AI system. Before the model, the fundamentals that keep it honest in production.

PythonasyncioGitREST

Programming and async

Core

Write clean, typed, concurrent services that hold up under real traffic.

Concepts

Structured concurrencyRun tasks as a group that starts and cancels together, so nothing leaks.

Structured concurrency is a programming paradigm that ties the lifetime of concurrent tasks to a lexical scope. Tasks spawned inside a scope cannot outlive it: when the block exits, every child task is cancelled and awaited before execution moves on. This prevents the class of bugs where a background task continues running after the code that started it has already returned, leaking resources or causing subtle state corruption.

In Python the pattern is most fully realized in Trio's nurseries and in asyncio's TaskGroup, added in Python 3.11. The guarantee matters especially in AI services where a single request may fan out into dozens of tool calls and retrieval steps: if the request is cancelled, every sub-task is cancelled with it rather than silently orphaned.

Sources

BackpressureKeep fast producers from drowning slow consumers under load.

Backpressure is the mechanism by which a slow consumer signals to a fast producer to slow down, rather than letting a queue grow unboundedly until memory is exhausted or messages are dropped. In an AI service, a common failure is a high-throughput ingest path that enqueues work far faster than the model or the downstream API can drain it. Without backpressure, the queue balloons, latency climbs, and the system eventually crashes or starts dropping requests silently.

Implementing backpressure usually means setting a bounded queue and blocking or rejecting new work when it is full, rather than accepting everything and hoping for the best. asyncio queues accept a maxsize argument for exactly this purpose.

Sources

Technologies

asyncioPython's event loop for concurrent I/O without threads.

asyncio is Python's built-in event loop and coroutine framework, introduced in Python 3.4 and stable since 3.7. It runs I/O-bound tasks concurrently on a single thread by suspending a coroutine at each await point and resuming another that is ready, without the overhead or complexity of threads. In AI services, nearly everything is I/O-bound: model API calls, database queries, embedding lookups, and tool calls all spend most of their time waiting for a network response rather than computing.

asyncio's native primitives (TaskGroup, Queue, timeout, gather) are the right building blocks for the concurrency layer of an AI backend. The key discipline is to keep CPU-bound work out of the event loop: any heavy computation should run in a thread pool via loop.run_in_executor.

Sources

PydanticTyped models that validate data at the boundary.

Pydantic is a Python data validation library built on type annotations. You declare the shape of data as a Python class, and Pydantic enforces that shape at runtime, raising a structured error if any field is wrong rather than letting malformed data propagate silently into business logic. It is the de-facto standard for validating data at service boundaries in Python: API request bodies, environment configuration, and crucially, model outputs that need to conform to a typed schema before your code acts on them.

Sources

In production

The discipline that separates a shipped system from a demo.

Deadline every callNo external call without a timeout; a hung dependency must never hang the whole system.

Every call to an external system, whether a model API, a database, or a third-party tool, must be wrapped in a timeout. Without one, a hung dependency can hold a connection open indefinitely, exhausting the thread pool or event loop and taking down the whole service. The timeout should be set at the point of the call, not assumed from a framework default, and its value should reflect the SLA you are trying to meet.

In asyncio, asyncio.timeout() and asyncio.wait_for() are the right primitives. The discipline is to wire a timeout before the first deploy, not after the first outage.

Sources

Degrade gracefullyDecide the fallback before the dependency fails, not in the middle of an incident.

Deciding the fallback behavior before a dependency fails is far easier than deciding it in the middle of an incident. Graceful degradation means your service keeps returning something useful, a cached result, a simplified response, or an honest error message, rather than crashing or hanging when a downstream system is unavailable. For AI services this often means falling back to a simpler model, returning a cached embedding, or surfacing a clear 'feature temporarily unavailable' message instead of a blank failure.

Sources

Data handling

Core

Move, clean, and shape the data a model depends on without surprises.

Concepts

Vectorized operationsTransform whole columns at once instead of Python loops.

Vectorized operations apply a computation to an entire array or column at once using compiled, SIMD-accelerated code, instead of looping element by element in Python. A Python for-loop over a million rows is orders of magnitude slower than the equivalent NumPy or pandas operation because it pays the interpreter overhead on every iteration. In data preparation pipelines that precede training or embedding generation, the difference between vectorized and loop-based code frequently decides whether a job finishes in seconds or hours.

Sources

Deterministic preprocessingSame input, same features, every run, so results reproduce.

A preprocessing pipeline is deterministic when the same raw input always produces the same features, regardless of when or where it runs. Non-determinism creeps in through random seeds not being set, statistics (mean, std) computed on a different subset of data, or external state such as the current date being baked into a feature. Non-deterministic pipelines make experiments impossible to reproduce and production behaviour impossible to reason about.

The fix is to treat every preprocessing decision as a parameter: fit any statistics on a fixed training split, version that fitted transformer alongside the model, and apply it identically at serving time.

Sources

Technologies

NumPyFast numeric arrays under almost every Python data tool.

NumPy is the foundational numeric array library for Python. Virtually every Python data and ML tool, including pandas, PyTorch, and scikit-learn, uses NumPy arrays as its underlying data representation. Fluency with NumPy's array model, broadcasting rules, and indexing conventions is a prerequisite for working effectively with any of them. For AI engineers the most common use cases are manipulating embedding vectors, performing distance computations, and converting between library formats.

Sources

pandasDataframes for cleaning and shaping tabular data.

pandas is the standard Python library for working with tabular data. Its core abstraction, the DataFrame, lets you load, inspect, filter, join, and reshape structured data without writing loops. In an AI engineering context, pandas is typically used for data exploration and cleaning before a training run, for preparing evaluation datasets, and for post-processing model outputs into a reportable form.

The key to using pandas well is to stay in vectorized operations: use .apply() only when no vectorized alternative exists, and prefer .str accessors, .dt accessors, and built-in aggregations over Python-level loops.

Sources

In production

The discipline that separates a shipped system from a demo.

Version datasetsSnapshot and pin data so an experiment still reproduces months later.

A dataset should be treated like source code: every version that a model was trained or evaluated on must be reproducible months or years later. Without versioning, you cannot bisect a performance regression, you cannot reproduce a reported result, and you cannot safely update the data without breaking past comparisons. The minimum viable approach is to snapshot datasets to immutable storage with a content hash and record that hash alongside the model checkpoint and eval results.

Sources

Validate on ingestReject malformed records at the door, before they reach training or eval.

Malformed records should be rejected at the point they enter the pipeline, not discovered downstream as a silent corruption of training features or evaluation results. Schema validation on ingest gives you a clean failure with a clear error message, rather than a wrong result days later. In practice this means running every incoming batch through a schema check, for example with Pydantic or Great Expectations, and routing failures to a dead-letter queue or an alert rather than silently dropping them.

Sources

ML fundamentals

Recommended

Enough model intuition to know what to reach for and when not to.

Concepts

Train / eval / test splitNever measure quality on data the model has already seen.

Splitting data into separate training, validation, and test sets is the foundational discipline that separates real measurements from optimistic self-delusion. The training set is what the model learns from. The validation set is used to tune hyperparameters and compare approaches. The test set is held out completely and touched only once, to report the final result. Using the test set more than once leaks information and causes the reported number to overestimate real-world performance.

For AI engineers working with LLMs, the principle carries over directly to prompt optimization and fine-tuning: measure quality on data the model or prompt has never been adjusted against.

Sources

Precision, recall, F1The metrics behind every honest claim about how well a model works.

Precision, recall, and F1 are the standard metrics for classification tasks where the class distribution is not equal. Precision is the fraction of positive predictions that were correct. Recall is the fraction of actual positives that were found. F1 is the harmonic mean of the two, penalising heavy imbalance between them. Knowing which to optimise for is a product decision: a spam filter that misses spam (low recall) is a different failure from one that blocks legitimate mail (low precision).

For LLM evaluation, these metrics translate directly to tasks like entity extraction, citation grounding checks, and retrieval evaluation, where you care both about finding all the relevant items and not surfacing irrelevant ones.

Sources

Overfitting and regularizationTell a model that learned the task from one that just memorized it.

Overfitting occurs when a model learns the training data so precisely that it fails to generalise to new examples. The model has effectively memorised noise rather than the underlying pattern. The diagnostic is a large gap between training and validation performance. Regularization techniques, such as L2 weight decay, dropout, and early stopping, constrain the model to prevent this by penalising complexity or limiting how long training runs.

For fine-tuned LLMs, overfitting on a small dataset is a common failure mode: the model loses its general capabilities while appearing to improve on the narrow training task. Holding out a capability evaluation set is the safeguard.

Sources

Technologies

PyTorchThe framework most models are built and run in.

PyTorch is the dominant framework for defining, training, and running neural network models in research and production. Its core abstraction is a tensor, a multi-dimensional array that supports automatic differentiation: you write the forward pass as ordinary Python, and PyTorch computes gradients automatically. The ecosystem around it, including Hugging Face Transformers, torchvision, and the fine-tuning libraries used throughout the roadmap, all build on PyTorch.

For AI engineers who are not training from scratch, PyTorch familiarity means being able to load a model checkpoint, run inference, interpret memory and compute costs, and understand why a fine-tune behaves as it does.

Sources

scikit-learnClassic models, metrics, and splits in one library.

scikit-learn is the standard Python library for classical machine learning: it provides a consistent API for dozens of algorithms alongside the preprocessing, cross-validation, and evaluation utilities that surround them. For AI engineers its most important role is not in building classifiers but in providing the tooling needed to measure them: train/test splitting, cross-validation, and the metrics module that implements precision, recall, F1, ROC-AUC, and many others. It is also the right tool for any task where a gradient-boosted tree or logistic regression will outperform or be cheaper than a neural approach.

Sources

In production

The discipline that separates a shipped system from a demo.

Beat a baseline firstIf a trivial baseline matches the model, the model is not earning its complexity.

Before investing in a sophisticated model, measure a trivially simple one. A majority-class classifier, a keyword rule, or a nearest-neighbour lookup over a small set of examples often achieves a surprisingly large fraction of the sophisticated model's performance. If the baseline already meets the bar, the complex model is not earning its cost or latency. If it does not, the baseline score gives you the minimum a real improvement must beat, which disciplines model selection and keeps eval results honest.

Sources

Hold out a real test setKeep an untouched set that mirrors production, not a random split of clean data.

The test set must mirror the distribution of real production inputs, not be a random slice of a clean benchmark dataset. A model that scores well on a random split of laboratory data can still fail badly on the noisy, domain-specific, time-shifted data it actually encounters in production. The discipline is to collect a representative sample of what the model will actually face before you start building, keep it locked, and use it only once to report the final result. Any use during development leaks information.

Sources

Engineering hygiene

Core

Version control, tests, and clean interfaces so AI work ships like real software.

Concepts

IdempotencySafe retries that never double-charge or double-write on a flaky network.

An operation is idempotent when calling it multiple times with the same inputs produces the same result as calling it once. On a flaky network, or when a client retries after a timeout, idempotency is what prevents a double-charge, a duplicate email, or a double-write to a database. For AI systems this matters most in tool-calling agents: a tool the model retries after a timeout must not apply its effect twice.

The standard implementation is to attach a client-generated idempotency key to each request. The server records completed operations keyed on that token and returns the cached result on a retry rather than re-executing.

Sources

Contract testingPin the shape of every interface so refactors stay safe.

Contract testing verifies that a consumer and a provider agree on the shape of the interface between them, independently, without needing to run both together. Rather than testing a live integration end-to-end on every build, each side asserts that it would produce or accept what the other expects. For AI services where a prompt schema, a tool definition, or an API response format is the contract, contract tests catch breaking changes in the interface before they reach production and cause silent misbehaviour.

Sources

Twelve-factor configSecrets and settings live in the environment, never in code.

The Twelve-Factor App's third factor states that configuration, anything that varies between deployment environments, must live in the environment, not hardcoded in code or checked into a repository. For AI services this means API keys, model endpoint URLs, feature flag values, and rate-limit thresholds are all read from environment variables at startup. The practical consequences are that no secret ever enters version control, deployments to staging and production are identical code with different environment, and rotating a credential requires no code change.

Sources

Technologies

GitVersion control every change runs through.

Git is the version control system that every code change, configuration update, and infrastructure declaration runs through. For AI engineering it has a broader scope than in traditional software: prompt versions, evaluation datasets, model configuration, and fine-tuning scripts all belong in Git alongside application code. A prompt change that is not tracked in version control cannot be rolled back, cannot be tied to an eval run, and cannot be reviewed before it ships.

The baseline discipline is to treat every artifact that affects model behaviour as code: branch it, review it, and merge it through the same process as everything else.

Sources

REST / JSONThe contract most services speak over the wire.

REST over HTTP with JSON bodies is the contract most services speak to each other over the wire. Understanding REST means understanding how HTTP status codes convey outcome (200 vs 400 vs 429 vs 500), how headers carry authentication and rate-limit information, and how to design idempotent endpoints. For AI services, this matters in both directions: your service exposes a REST API to callers, and it calls model provider APIs that are themselves REST services with specific retry and rate-limiting semantics that must be handled correctly.

In production

The discipline that separates a shipped system from a demo.

Trace IDs end to endTag every request so you can follow one user's path across services and logs.

A trace ID is a unique identifier generated at the start of a request and propagated through every downstream call that request makes. When a request goes wrong, you look up that ID in your log aggregator or trace store and see the entire causal chain: the original input, every service call, every model invocation, and the final output. Without trace IDs, debugging a multi-service AI system means correlating log lines across services by timestamp, which is slow, error-prone, and often impossible.

The implementation is trivial: generate a UUID at the boundary, pass it in a header (e.g. X-Request-ID), and log it on every line. The returns are immediate.

Sources

Flag risky changesShip behind a feature flag so a bad prompt or model can be killed in seconds.

A feature flag lets you deploy a change to production without exposing it to users, then gradually roll it out while watching metrics. For AI systems, where a prompt change or a model swap can shift behaviour in ways that only become visible at scale, flags are the primary safety mechanism for releases. If a new prompt degrades quality or causes unexpected behaviour, you flip the flag to disable it in seconds rather than deploying a rollback.

The discipline is to default new AI behaviour to off, ship the flag infrastructure first, and never hard-cut a model or prompt change straight to all users.

Sources

Put this whole roadmap on your team.

Every layer above is someone you can hire, production-proven and embedded in your team in days. Tell us what you are building and we will line up a shortlist.