Composable Graph Architecture — Design Summary

We discussed how to model and manage deeply nested, reusable computation graphs in a low-code environment. Key design decisions and strategies:


1. Graph Structure and Routing

  • Use namespaced routes like /app/graph/:graphId for persisted graphs and /app/graph for creating new graphs with immediate redirect.
  • Subgraphs are reusable compositions; they should be instantiated per call site to ensure isolation of state and wiring.

2. Instance Management

  • Avoid cloning full subgraph structures unless necessary.
  • Prefer template + override modeling:
    • Templates define shared structure (sockets, logic).
    • Instances override only the minimal set of props/values.
  • Maintain per-instance identity while referring to shared structure.

3. Socket Resolution

  • Store only socket overrides in the instance.
  • At runtime or render time, use a resolveSocket() function to merge instance data with template defaults.
  • This avoids memory overhead from instantiating all sockets eagerly.

4. Composition Usages

  • Track which nodes instantiate a given subgraph within the same store/slice as templates.
  • Maintain an index: usages: Record<templateId, Set<nodeIds>> to support reverse lookups, updates, and synchronization.

5. Evaluation and Efficiency

  • Graph evaluation should work via contextual resolution, not full materialization.

  • Lazy instantiation of socket state is not premature optimization — it's a necessary boundary for performance and structural correctness in compositional systems.

    Screenshot_2025-05-29_at_9.21.24_PM.png