# How the Egonex AI Graph Layout Algorithm Scales to Thousands of Nodes

> Discover how the Egonex AI graph layout algorithm scales to thousands of nodes using a hybrid strategy. Learn about its efficient handling of complex knowledge graphs.

- Repository: [Egonex/Understand-Anything](https://github.com/Egonex-AI/Understand-Anything)
- Tags: performance
- Published: 2026-06-20

---

**The Egonex AI dashboard uses a hybrid layout strategy that combines the Eclipse Layout Kernel (ELK) running in a WebAssembly worker for hierarchical structural views, and a custom force-directed algorithm with dynamic force scaling and bounded simulation ticks for knowledge graphs containing thousands of nodes.**

The `Egonex-AI/Understand-Anything` repository implements a sophisticated graph visualization system capable of rendering everything from small project trees to massive knowledge graphs with loose connectivity. Understanding how the Egonex AI graph layout algorithm maintains performance at scale requires examining the dual-engine approach implemented in [`packages/dashboard/src/utils/layout.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/src/utils/layout.ts) and [`packages/dashboard/src/utils/elk-layout.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/src/utils/elk-layout.ts).

## Hybrid Layout Architecture

The dashboard selects between two distinct layout engines based on graph characteristics. **Structural views**—such as project trees and guided tours—use the deterministic **ELK** (Eclipse Layout Kernel) engine. **Knowledge graphs**—large, loosely-connected node clouds—leverage a custom **force-directed layout** built on `d3-force`.

This separation allows each algorithm to optimize for its specific workload: ELK handles hierarchical constraints with O(N log N) efficiency, while the force-directed approach uses heuristics to cap computational complexity for unstructured data.

## Force-Directed Layout for Massive Knowledge Graphs

The core scaling logic resides in [`packages/dashboard/src/utils/layout.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/src/utils/layout.ts) within the `applyForceLayout` function. This implementation automatically adjusts simulation parameters based on graph size to prevent the O(N²) performance degradation typical of naive force-directed algorithms.

### Dynamic Force Parameters

When `nodes.length` exceeds 100, the algorithm switches to **large-graph mode** with aggressive spacing parameters:

```typescript
const isLarge = nodes.length > 100;
const chargeStrength = isLarge ? -600 : -350;  // Stronger repulsion
const linkDistance = isLarge ? 250 : 150;     // Longer edges

```

The **charge strength** becomes more negative (`-600` vs `-350`) to push nodes apart aggressively, preventing dense clumps that degrade readability. Simultaneously, **link distance** increases from 150px to 250px, giving edges more room and reducing crossings in large node clouds.

### Adaptive Cluster Radius

For graphs with community data, the algorithm scales the clustering radius linearly with node count:

```typescript
const clusterRadius = Math.max(600, nodes.length * 5);

```

This ensures that as graphs grow into thousands of nodes, community centers spread farther apart, maintaining visual separation between logical groups while the force simulation continues to optimize local node positions.

### Bounded Computation Cost

The critical scalability mechanism limits simulation ticks based on graph size:

```typescript
const ticks = Math.min(300, Math.max(100, nodes.length));
sim.tick(ticks);
sim.stop();

```

Even a 5,000-node graph never executes more than 300 simulation steps. Because each tick touches every node and edge once, this creates **linear-ish performance** (O(N × ticks)) rather than the unbounded growth of traditional force simulations that run until convergence.

### Collision Detection with Node Dimensions

The simulation respects actual node dimensions to prevent overlap:

```typescript
.force("collide", forceCollide<ForceNode>()
  .radius((d) => {
    const dims = nodeDimensions?.get(d.id);
    return Math.max(20, ((dims?.width ?? NODE_WIDTH) + 40) / 2);
  })
  .strength(0.8))

```

This ensures that when nodes have custom widths and heights, the force calculation accounts for their real size, eliminating expensive post-processing overlap removal.

## ELK Layout for Structural Views

Hierarchical graphs use the deterministic ELK engine running in a WebAssembly worker ([`packages/dashboard/src/utils/elk-layout.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/src/utils/elk-layout.ts)). The implementation converts React Flow nodes into `ElkInput` format, processes them through the compiled ELK binary, and merges results back via `mergeElkPositions`.

ELK uses a **layered algorithm** with O(N log N) complexity:

```typescript
export const ELK_DEFAULT_LAYOUT_OPTIONS: Record<string, string> = {
  algorithm: "layered",
  "elk.direction": "DOWN",
  "elk.layered.spacing.nodeNodeBetweenLayers": "80",
  "elk.spacing.nodeNode": "60",
  "elk.layered.crossingMinimization.strategy": "LAYER_SWEEP",
  "elk.edgeRouting": "ORTHOGONAL",
};

```

Because ELK runs in a WebAssembly worker ([`src/utils/layout.worker.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/src/utils/layout.worker.ts)), it handles thousands of nodes without blocking the main thread, maintaining UI responsiveness during layout computation.

## Legacy Dagre Fallback

A tertiary fallback (`applyDagreLayout`) remains available for legacy structural views. When `nodes.length > 50`, this engine automatically increases `nodesep` and `ranksep` parameters to maintain legibility. However, production deployments now prefer ELK for all structural layouts due to superior crossing minimization.

## Practical Implementation Examples

### Rendering a Large Knowledge Graph

```typescript
import { applyForceLayout } from "./utils/layout";

const nodes = [
  { id: "A", type: "custom", data: {}, position: { x: 0, y: 0 } },
  { id: "B", type: "custom", data: {}, position: { x: 0, y: 0 } },
  // ... thousands more nodes ...
];
const edges = [{ id: "e1", source: "A", target: "B" }];

// Optional community mapping for clustering
const communityMap = new Map<string,number>([
  ["A", 0],
  ["B", 1],
]);

const { nodes: laidOut } = applyForceLayout(
  nodes,
  edges,
  undefined,      // optional node dimensions
  communityMap,
);

```

### Processing Hierarchical Data with ELK

```typescript
import { nodesToElkInput, applyElkLayout, mergeElkPositions } from "./utils/elk-layout";

const elkInput = nodesToElkInput(nodes, edges, dimensionMap);
const positioned = await applyElkLayout(elkInput);  // WebAssembly worker
const positionedNodes = mergeElkPositions(nodes, positioned);

```

### Intelligent Layout Selection

```typescript
function layoutGraph(nodes: Node[], edges: Edge[]) {
  if (nodes.length < 2000 && isHierarchical(nodes, edges)) {
    return layoutWithELK(nodes, edges);
  }
  return applyForceLayout(nodes, edges);  // Scales to thousands
}

```

## Summary

- **Hybrid engine selection**: ELK handles hierarchical structural views in O(N log N) time, while force-directed layouts manage large knowledge graphs with linear-ish complexity.
- **Dynamic parameter scaling**: The algorithm adjusts charge strength (-600), link distance (250px), and cluster radius (`nodes.length * 5`) when graphs exceed 100 nodes.
- **Bounded computation**: Simulation ticks cap at 300 regardless of graph size, preventing CPU spikes on massive datasets.
- **WebAssembly isolation**: ELK processing occurs in a dedicated worker, keeping the main thread responsive for graphs exceeding 3,000 nodes.
- **Collision awareness**: Force calculations incorporate actual node dimensions to prevent overlap without additional post-processing.

## Frequently Asked Questions

### How does the algorithm handle 5,000+ nodes without freezing the browser?

The `applyForceLayout` function in [`packages/dashboard/src/utils/layout.ts`](https://github.com/Egonex-AI/Understand-Anything/blob/main/packages/dashboard/src/utils/layout.ts) limits simulation ticks to a maximum of 300 using `Math.min(300, Math.max(100, nodes.length))`. This caps the computational cost at O(N × 300) rather than allowing indefinite iteration. Additionally, ELK layouts execute in a WebAssembly worker, preventing main-thread blockage during layout calculation.

### What is the difference between ELK and force-directed layouts in Egonex AI?

**ELK** (Eclipse Layout Kernel) is used for structural views like project trees and tours because it produces deterministic, hierarchical layouts with minimized edge crossings using a layered algorithm. **Force-directed layouts** are reserved for knowledge graphs—large, loosely-connected node clouds—because they can handle arbitrary graph topologies and scale efficiently through the dynamic parameter adjustments implemented in `applyForceLayout`.

### Why does the force-directed algorithm use different parameters for large graphs?

When `nodes.length` exceeds 100, the algorithm switches `chargeStrength` from -350 to -600 and `linkDistance` from 150px to 250px. These adjustments prevent node clustering and edge crossings that would otherwise make large graphs unreadable. The stronger repulsion forces and longer edge distances maintain visual clarity as node density increases.

### How does community clustering improve layout performance?

The optional `communityMap` parameter triggers additional centering forces (`clusterX` and `clusterY`) that group related nodes into logical layers arranged in a circle with radius `max(600, nodes.length * 5)`. This pre-structuring reduces the randomness the simulation must resolve, allowing the layout to stabilize within the bounded tick count while maintaining clear separation between distinct groups.