“It already works —
it just needs productionising.”
That sentence is the whole job.
Python engineers who can take the analyst's notebook, the founder's script or the data scientist's proof of concept and return a service with owners, alerts and a rollback. Full-time in your team, on the Virtus payroll.
Eleven lines that work, and seven questions they never answer
This cell is real, give or take the variable names. It is correct. It is also three weeks away from being something you can put on a rota — and the gap on the right is exactly what you are hiring for.
df = pd.read_csv("orders_latest.csv")
df = df[df.status == "shipped"]
rates = requests.get(FX_URL).json()
df["usd"] = df.total * rates[df.currency]
model = pickle.load(open("model.pkl", "rb"))
df["risk"] = model.predict(df[FEATURES])
df.to_csv("out.csv")
print("done", len(df))Nothing here is wrong. That is what makes it dangerous — it will run correctly every day until the morning it does not.
Where does the file come from?
A path on someone's laptop becomes an object store key, a signed URL and a retry when the upload is still in flight.
What if the schema changed?
Pandera or Pydantic at the boundary, so a renamed column fails loudly on row zero instead of silently producing nulls.
What if the FX call fails?
A timeout, a bounded retry with jitter, a cached last-known-good rate, and an alert when the cache is what got used.
Which model is that, exactly?
A pickle with no version is an outage waiting to happen. Model artefacts get a registry, a hash and a rollback path.
What happens on the second run?
Idempotency. Re-running must not double-count, and a partial failure must be safe to replay.
Who finds out it broke?
Structured logs with a correlation id, a metric on rows processed, and an alert that names the owner.
How fast is it on 40× the data?
Chunking, vectorisation, or a move to Polars or DuckDB — decided by measurement, not by preference.
Six things they are hired for
Web services
FastAPI or Django REST, typed with Pydantic, documented by OpenAPI, and deployed as a container rather than a cron job.
Background processing
Celery, RQ or Arq with visibility timeouts, dead-letter queues and tasks that are safe to retry.
Data work
pandas, Polars and DuckDB, plus the SQL underneath — and knowing when the answer is a warehouse query rather than Python at all.
Automation & integrations
Long-running scrapers, ERP connectors and file feeds, built to survive the source changing without telling you.
Packaging that behaves
uv or Poetry, pinned and locked, one Dockerfile, and an environment that reproduces on someone else's machine.
Tests worth running
pytest with fixtures that are not a fixture soup, factory data, and coverage on the branches that matter rather than a headline number.
Three bands
If you are hiring to harden something that already exists, hire senior. If you are hiring to add endpoints to a service someone else designed, mid-level is the better value.
If it is really a pipeline, hire a data engineerMid-level
3–5 yrs$28–34/hrBuilds endpoints and jobs in an existing service. Comfortable with the framework; still learning production hardening.
Senior
5–8 yrs$34–44/hrTurns a proof of concept into a service with owners, alerts and a rollback. Reads a profiler.
Lead
8+ yrs$44–58/hrSets the architecture and the packaging standards across teams, and picks the fights worth having about typing.
Send us the script that is holding something up
We will tell you what it takes to make it something you can rely on, and whether that is one engineer for a month or three.
