Production data pipelines without leaving your codebase · Updated May 2026
TL;DR
You're building data pipelines or analytics tools in TypeScript and wondering if you need to rewrite everything in Python. Short answer: probably not. TypeScript has a viable data science stack in 2026—Arquero for DataFrames (210k monthly downloads), DuckDB for SQL analytics, Observable Plot for visualization. Python still wins for exploratory analysis and ML training, but TypeScript excels at production deployment, type-safe pipelines, and integrated backend data handling.
Why TypeScript for Data Science?
The Problem
You're a TypeScript developer working on a web application. Product asks for:
"Can we add a dashboard showing weekly sales trends?"
"Users need to download a CSV of their analytics data"
"We need to calculate percentile rankings in real-time"
Your instinct: spin up a Python microservice. But now you're maintaining two codebases, two deployment pipelines, and a serialization boundary between them. Every schema change requires updating both sides. Your TypeScript team can't debug the Python service. Your iteration speed drops.
The alternative: Handle the data science work in TypeScript, using the same runtime, types, and deployment pipeline as your application layer.
When TypeScript Makes Sense
Use TypeScript when...
Stick with Python when...
Building production applications with embedded analytics
Doing exploratory data analysis in Jupyter notebooks
Need type-safe data transformations in existing codebase
Need statistical modeling (scikit-learn, statsmodels)
Want fast iteration without a separate Python service
Training ML models (PyTorch, TensorFlow)
Data fits in memory (up to several GB)
Working with scientific computing libraries (NumPy, SciPy)
Team is TypeScript-native and deployment simplicity matters
Team is primarily data scientists, not web developers
"For data science work, pandas, numpy, matplotlib, and Jupyter notebooks form Python's data science stack, with nothing in the TypeScript world coming close for exploratory data analysis."
True. But the same article notes:
"TypeScript requires developers to invest time in type definitions, but this upfront investment pays dividends in developer productivity and code maintenance."
The 2026 reality: Use both. Python for research and model training, TypeScript for production deployment and application integration.
Quick Win: Your First TypeScript Data Pipeline
Let's build a real data pipeline in TypeScript. Problem: analyze product sales from a CSV, calculate category totals, and find top performers.
Why Arquero over alternatives (Danfo.js, data-forge-ts, pandas-js):
Adoption: 210k monthly npm downloads (verified 2026-05-25) vs. Danfo.js's 23k
Performance: Efficient in-memory operations with Arrow export support for zero-copy data transfer
API design: Inspired by R's dplyr, familiar to data scientists
Maintenance: Active development by University of Washington team
Core operations:
import * as aq from 'arquero';
import { op } from 'arquero';
const data = aq.table({
date: ['2026-01-01', '2026-01-02', '2026-01-03'],
value: [100, 150, 120],
category: ['A', 'B', 'A']
});
// Transformations
const result = data
.derive({
normalized: d => d.value / op.max(d.value),
date_parsed: d => op.parse_date(d.date)
})
.filter(d => d.category === 'A')
.select('date', 'value', 'normalized');
// Aggregations
const summary = data
.groupby('category')
.rollup({
mean: d => op.mean(d.value),
median: d => op.median(d.value),
std: d => op.stdev(d.value)
});
// Export
const csv = result.toCSV();
const json = result.objects();
const arrow = result.toArrow();
Visualization: Observable Plot
5,277 GitHub starsLast commit: 2026-05-16
Why Observable Plot:
Built by the D3 team as a high-level alternative
Grammar-of-graphics API: concise syntax for common charts
Full TypeScript support with excellent type definitions
A histogram in D3 requires ~50 lines; Plot does it in one
Runtime Choice: Bun vs. Deno vs. Node.js
TypeScript execution models differ across runtimes:
Bun: Direct execution (no transpilation)
Deno: Direct execution (no transpilation)
Node.js: Type-stripping only (via --experimental-strip-types flag) - transforms, enums, and decorators still require transpilation
Performance comparison (2026 benchmarks):
Metric
Bun
Deno
Node.js
HTTP throughput
52k req/sec
29k req/sec
14k req/sec
Cold start
8-15ms
40-60ms
60-120ms
Recommendation:
Bun: Default for most TypeScript data work (fast, simple, great DX)
Deno: Use if you're running WASM-heavy workloads (better V8 optimization)
Node.js: Use if you need ecosystem compatibility or existing tooling
Patterns: Real-World TypeScript Data Engineering
Pattern 1: Type-Safe ETL Pipelines
Problem: You're ingesting data from an API, transforming it, and loading it into a database. You want compile-time guarantees that your transformations are correct.
Solution: Use Zod for schema validation and TypeScript types for transformations.
import * as aq from 'arquero';
import { op } from 'arquero';
import { z } from 'zod';
const SalesRecordSchema = z.object({
id: z.string(),
product_id: z.string(),
amount: z.number().positive(),
timestamp: z.string().datetime(),
customer_id: z.string().optional()
});
type SalesRecord = z.infer;
async function extractTransformLoad(sourceUrl: string): Promise {
const response = await fetch(sourceUrl);
const rawData = await response.json();
// Validate schema
const validated = rawData.map((row: unknown) =>
SalesRecordSchema.parse(row)
);
// Transform with Arquero
const table = aq.from(validated)
.derive({
amount_usd: d => d.amount / 100,
date: d => op.parse_date(d.timestamp),
hour: d => op.hour(op.parse_date(d.timestamp))
})
.filter(d => d.amount_usd > 0)
.select('id', 'product_id', 'amount_usd', 'date', 'hour', 'customer_id');
return table;
}
Benefits:
Zod validates incoming data at runtime
TypeScript catches type errors in transformations
Refactoring is safe: rename a field, compiler finds all usages
IDE autocomplete works throughout the pipeline
Pattern 2: Streaming Aggregations
Problem: You're building a real-time analytics dashboard. Data arrives in batches; you need to update aggregates efficiently.
Solution: Maintain aggregated state with Arquero, update incrementally.
See the full guide for complete code examples.
When to Switch from Python
You Should Switch When...
Type safety is blocking production deployment: Your data pipeline has runtime errors because someone renamed a field or changed a type
You're duplicating logic across Python and TypeScript: Your backend data transformations mirror your frontend display logic
Your data science work is integration, not research: You're building production features that consume ML outputs or analytics
Your data fits in memory: TypeScript data tools work best with datasets up to several GB
Your team is primarily TypeScript developers: Training web developers in TypeScript data tools is faster than teaching them Python