I am building ProductBay (productbay.io), a verified B2B matching network where companies buy each other's software and services, so software spend brings paying customers back. Under the business idea sits a nice little graph problem, and I want to walk through it because the obvious approach (match pairs) mostly does not work.
The naive model: pairs
Every company in the network publishes two lists: what it sells and what it needs. The naive idea is to look for pairs: company A needs what B sells, and B needs what A sells. Both buy, both get a customer.
In practice pairs are rare. A company selling a CRM needs HR software. The HR vendor needs a marketing tool. The marketing tool needs a CRM. Nobody forms a pair, but the three of them form a perfect loop.
The better model: a directed graph and its cycles
Model each company as a node. Draw an edge A -> B when A needs what B sells (and B passes A's fit criteria). A "match" is now a directed cycle: everybody in the cycle buys from the next company and sells to the previous one, so every participant gets exactly one supplier and one customer.
// needs: Map<companyId, Set<companyId>> (A -> suppliers A would buy from)
function shortCycles(needs, start, maxLen = 4) {
const out = [];
const path = [start];
const seen = new Set([start]);
(function dfs(node) {
for (const next of needs.get(node) ?? []) {
if (next === start && path.length >= 2) out.push([...path]);
else if (!seen.has(next) && path.length < maxLen) {
seen.add(next); path.push(next);
dfs(next);
path.pop(); seen.delete(next);
}
}
})(start);
return out;
}
Short cycles matter. A cycle of two or three companies is easy to explain and easy to accept. A cycle of eight companies is fragile: one "no" breaks it. So we cap the length and score cycles by fit, not by how clever they are.
Constraints that shape the algorithm
The interesting part is not finding cycles, it is the rules around them:
- Fit first. An edge only exists if the buyer would buy that product anyway. Reciprocity never creates an edge on its own; it only ranks between edges that already make sense.
- Full price, real orders. Every edge is a normal order at the seller's published price. No netting, no credits. That keeps the graph honest: nobody can "pay" with favours.
- All or nothing. A cycle only becomes real when every company in it accepts. Until then, nothing is charged. Each company has a limited window (24 hours) to accept; if it declines, the request goes to the next best candidate that fits.
- Linked cancellation. If one company in the cycle cancels its order, the other orders in that match are cancelled too, so nobody keeps paying a supplier after their own customer has left.
- Trial before payment. Every match starts with a 7-day free trial on both sides. Payment starts only when the trial ends.
Trust is a graph property too
A cycle is only as good as its weakest node. That is why verification happens before a company gets any edges at all: business check (KYB), founder identity, an active payment account, a live product, and a hands-on test by our team. Reputation (completed orders, renewals, reviews from verified buyers) then becomes an edge weight.
Why I think this is worth building
Most small B2B companies spend a large part of their budget on tools from vendors that will never buy anything from them, and then pay again to find customers. A network that turns some of that spend into customers builds something like a startup cluster: a startup ecosystem where startups buying from startups is the normal case, not a lucky coincidence.
ProductBay.io launches in Q4 2026. If you run a B2B product and want to see which of your future suppliers need what you sell, the waitlist is open at productbay.io. And if you have solved a similar cycle-matching problem (kidney exchange is the classic reference), I would love to hear how you handled fragile long cycles.


Top comments (0)