HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
TimelyDataflow
differential-dataflow
Rust2019–2026
TimelyDataflow / differential-dataflow

differential-dataflow

An implementation of differential dataflow using timely dataflow on Rust.

24Distinct people
37Mentions
0Explicit recommenders
3KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

An implementation of differential dataflow using timely dataflow on Rust.

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 7:56:55 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year37 dated mentions

Observed mentions: 2019-03-11 00:45:13 UTC to 2026-07-14 04:51:30 UTC.

0369122019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 4 mentions; 1 submissions, 3 comments20192020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 12 mentions; 0 submissions, 12 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 12 mentions; 0 submissions, 12 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments20222023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 2 mentions; 1 submissions, 1 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC413
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC12012
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC12012
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC303
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC303
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC101
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC000
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC211

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
Differential Dataflow An implementation of differential dataflow over timely dataflow on Rust. Background Differential dataflow is a data-parallel programming framework designed to efficiently process large volumes of data and to quickly respond to arbitrary changes in input collections. You can read more in the differential dataflow mdbook and in the differential dataflow documentation. Differential dataflow programs are written as functional transformations of collections of data, using familiar operators like map, filter, join, and reduce. Differential dataflow also includes more exotic operators such as iterate, which repeatedly applies a differential dataflow fragment to a collection. The programs are compiled down to timely dataflow computations. For example, here is a differential dataflow fragment to compute the out-degree distribution of a directed graph (for each degree, the number of nodes with that many outgoing edges): let out_degr_dist = edges.map(|(src, _dst)| src) // extract source .count() // count occurrences of source .map(|(_src, deg)| deg) // extract degree .count(); // count occurrences of degree Alternately, here is a fragment that computes the set of nodes reachable from a set roots of starting nodes: let reachable = roots.iterate(|scope, reach| edges.enter(scope) .semijoin(reach) .map(|(src, dst)| dst) .concat(reach) .distinct() ) Once written, a differential dataflow responds to arbitrary changes to its initially empty input collections, reporting the corresponding changes to each of its output collections. Differential dataflow can react quickly because it only acts where changes in collections occur, and does no work elsewhere. In the examples above, we can add to and remove from edges, dynamically altering the graph, and get immediate feedback on how the results change: if the degree distribution shifts we'll see the changes, and if nodes are now (or no longer) reachable we'll hear about that too. We could also add to and remove from roots, more fundamentally altering the reachability query itself. Be sure to check out the differential dataflow documentation, which is continually improving. An example: counting degrees in a graph. Let's check out that out-degree distribution computation, to get a sense for how differential dataflow actually works. This example is examples/hello.rs in this repository, if you'd like to follow along. A graph is a collection of pairs (Node, Node), and one standard analysis is to determine the number of times each Node occurs in the first position, its "degree". The number of nodes with each degree is a helpful graph statistic. To determine the out-degree distribution, we create a new timely dataflow scope in which we describe our computation and how we plan to interact with it. // create a degree counting differential dataflow let (mut input, probe) = worker.dataflow(|scope| { // create edge input, count a few ways. let (input, edges) = scope.new_collection(); let out_degr_distr = edges.map(|(src, _dst)| src) // extract source .count() // count occurrences of source .map(|(_src, deg)| deg) // extract degree .count(); // count occurrences of degree // show us something about the collection, notice when done. let probe = out_degr_distr .inspect(|x| println!("observed: {:?}", x)) .probe(); (input, probe) }); The input and probe we return are how we get data into the dataflow, and how we notice when some amount of computation is complete. These are timely dataflow idioms, and we won't get in to them in more detail here (check out the timely dataflow repository). If we feed this computation with some random graph data, say fifty random edges among ten nodes, we get output like Echidnatron% cargo run --release --example hello -- 10 50 1 inspect Finished release [optimized + debuginfo] target(s) in 0.05s Running `target/release/examples/hello 10 50 1 inspect` observed: ((3, 1), 0, 1) observed: ((4, 2), 0, 1) observed: ((5, 4), 0, 1) observed: ((6, 2), 0, 1) observed: ((7, 1), 0, 1) round 0 finished after 772.464µs (loading) This shows us the records that passed the inspect operator, revealing the contents of the collection: there are five distinct degrees, three through seven. The records have the form ((degree, count), time, delta) where the time field says this is the first round of data, and the delta field tells us that each record is coming into existence. If the corresponding record were departing the collection, it would be a negative number. Let's update the input by removing one edge and adding a new random edge: observed: ((2, 1), 1, 1) observed: ((3, 1), 1, -1) observed: ((7, 1), 1, -1) observed: ((8, 1), 1, 1) round 1 finished after 149.701µs We see here some changes! Those degree three and seven nodes have been replaced by degree two and eight nodes; looks like one node lost an edge and gave it to the other! How about a few more changes? round 2 finished after 127.444µs round 3 finished after 100.628µs round 4 finished after 130.609µs observed: ((5, 3), 5, 1) observed: ((5, 4), 5, -1) observed: ((6, 2), 5, -1) observed: ((6, 3), 5, 1) observed: ((7, 1), 5, 1) observed: ((8, 1), 5, -1) round 5 finished after 161.82µs Well a few weird things happen here. First, rounds 2, 3, and 4 don't print anything. Seriously? It turns out that the random changes we made didn't affect any of the degree counts, we moved edges between nodes, preserving degrees. It can happen. The second weird thing is that in round 5, with only two edge changes we have six changes in the output! It turns out we can have up to eight. The degree eight gets turned back into a seven, and a five gets turned into a six. But: going from five to six changes the count for each, and each change requires two record differences. Eight and seven wer
Read the full README on GitHub

What Hacker News says

3 sources
Sure! So first, being in C/asm/.. is not incompatible with what i say: i'm saying that some of these are not hand-written, but are generated. So off the top of my head: - FFTW: an ocaml synthesizer for fft kernels from a fourier-transform DSL - basically all SQL engines, in particular the "query planner" part, which compiles an SQL query (functional spec based on the theory of relational algebra) into an imperative program (eg https://sqlite.org/opcode.html) - https://github.com/mit-plv/fiat-crypto, verified crypto routines - https://www.flopoco.org/, float cores for fpga - https://faust.grame.fr/, audio synthesis from a functional stream-based language - tensorflow and other "static graph" neural-whatever-matrix-multiplication-libs (https://ocaml.xyz/tutorial/cgraph.html) - https://github.com/timelydataflow/differential-dataflow, increme
Read the rest
ntal dataflow computations edit: i almost forgot all the openssl perl scripts, even if it can be seen more as macro-expansion than actual meta-programing/program synthesis: https://github.com/search?l=Perl&q=repo%3Aopenssl%2Fopenssl+... Basically all crypto libs use at least some form of compile-time execution to generate constants, offsets, tables, .. edit2: also svelte, a "virtual virtual" dom js thingy, never looked much into it, but afaik they do compile-time diffing, and thus generate imperative code (ie ugly old-school efficient spaghetti) from react-like vdom code.
In Program Synthesis is Possible (2018)
hi! sujay from convex here. I remember reading about your "reverse query engine" when we were getting started last year and really liking that framing of the broadcast problem here. as james mentions, we entirely re-run the javascript function whenever we detect any of its inputs change. incrementality at this layer would be very difficult, since we're dealing with a general purpose programming language. also, since we fully sandbox and determinize these javascript "queries," the majority of the cost is in accessing the database. eventually, I'd like to explore "reverse query execution" on the boundary between javascript and the underlying data using an approach like differential dataflow [1]. the materialize folks [2] have made a lot of progress applying it for OLAP and readyset [3] is using similar techniques for OLTP. [1] https://githu
Read the rest
In Convex vs. Firebase

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.