Our app models directed graphs in Postgres with a closure table (the transitive edges between nodes).
The advantages are that it's just sql, has good performance, and we can query the graph using relational logic rather than n+1 traversal. The trade off is space (the closure table has the potential to be huge).
So it depends on the size of the data set. Part of me wishes we'd built something that's easier to partition, but for now that's a future concern.