WESLEY WITSKEN

Methodology

The Shadow Data Layer

A repeatable pattern for extending Vantagepoint past its native limits.

Last updated: July 2026

What Triggers It

Vantagepoint only shows you the current state of data. It has no native memory, no native way to aggregate across the Work Breakdown Structure in flexible groupings, and no native way to pull related data together across separate hubs.

Three recurring client request shapes all trace back to that same underlying limitation.

Trigger 1

Snapshots in time

A client wants to see something like Work-in-Progress trended historically — “what did WIP look like three months ago?” VP can’t answer that natively. WIP is a live calculation: anything marked ready-for-billing today may be billed, written off, or adjusted by the time you’d want to look back at it. There’s no native mechanism to freeze a moment and preserve it. This shape shows up constantly — clients want to trend something over time that VP only ever shows as “right now.”

Trigger 2

Cross-project WBS aggregation

A client wants to roll up data across the Work Breakdown Structure in ways VP’s dashpart engine doesn’t support — for example, aggregate financials for “every Phase 20 across every project in the system.” Native dashparts don’t let you drill into or group by WBS levels this way; the only path is table view, manually drilling into individual records, with no way to group across projects by shared phase numbers or similar attributes.

Trigger 3

Cross-hub aggregation

A client wants data pulled together from entirely separate hubs — Employees and Projects, or Contacts and Projects — into a single consolidated view. Dashparts are natively scoped to a single hub’s data model, so combining, say, employee attributes with project financials in one place is out of reach without a custom structure to merge them into.

In all three cases, the pattern is the same: the request is almost always a variation on something VP can already show at a single point in time, a single level, or a single hub. The actual gap is getting VP to extend that same view across time, across a grouping, or across hubs it wasn’t designed to combine.

The Mechanism

  1. 01

    Reproduce the base view.

    Start from whatever existing dashpart or view the client is already looking at, and rebuild it inside a personal demo database. This gives a safe, controlled environment to probe without touching client data or systems.

  2. 02

    Isolate the query via profiler.

    Inside the dashpart’s search definition, add a deliberate dummy filter condition — something with no real match in the data. That condition becomes a unique fingerprint. Open the profiler, filter the captured query log down to statements containing that fingerprint, and the exact behind-the-scenes SQL VP is running to build the dashpart surfaces directly.

  3. 03

    Simplify and understand.

    Run the captured SQL through simplification to strip it down to its essential logic. The goal is understanding the bones of what VP is actually doing, not preserving its exact query verbatim.

  4. 04

    Design the shadow structure.

    Build a custom hub to hold the transformed/snapshotted data. Two design choices have held up across every build:

    • Avoid subgrids inside the custom hub. A flat structure makes calculated fields easier to build and makes the hub easier to search and consume from a dashpart.
    • No manual data entry. The hub exists purely as a transformation and storage layer — nobody touches it directly; it’s populated entirely on a schedule.
  5. 05

    Build the stored procedure.

    Almost always structured as a MERGE statement, pulling from VP’s Project hub, transforming it as needed, and merging the result into the custom hub on a scheduled basis.

  6. 06

    Build the consuming dashpart.

    Once the shadow hub is reliably populated, a native VP dashpart pulls from it like any other data source — producing the trend chart, cross-project rollup, or snapshot view the client originally asked for.

What’s Reusable vs. What’s Custom

Reusable across every engagement

  • — The six-step sequence itself
  • — Standard Project fields used for grouping; these carry over almost unchanged
  • — The core table joins, including the Project Summary table

Custom every time

  • — The specific fields and calculations inside the shadow hub
  • — The exact MERGE logic and transformation rules; every client’s data nuances differ
  • — The final dashpart design, shaped by how the client wants to consume the result

Worth calling out

The Project Summary table deserves its own mention. It’s one of the most valuable tools in the pattern, and it’s almost entirely unknown to clients. It’s VP’s own scheduled summarization layer for project financial data — built by Deltek for caching and performance, and explicitly documented as the recommended starting point for custom work, specifically to avoid parsing VP’s raw accounting tables directly. Nearly every client has it running and has no idea what it does. Using it as a foundation has saved significant development time across engagements.

Where It Gets Hard

The pattern is reliable, but it isn’t mechanical. Two failure modes show up repeatedly.

Failure mode

Merge key integrity

The MERGE statement’s correctness lives or dies on getting the matching keys right, especially across WBS levels. Get the key definition even slightly wrong, and the merge won’t recognize a record already exists — it creates a duplicate, or fails to write into the correct row. There’s no dramatic error message when this happens. The job runs, and the data is just quietly wrong.

The validation approach that’s held up: run the custom hub’s output side by side against the original client dashpart being reverse-engineered, and check for drift. The Project Review area is a second independent check. Looping in the client and other consultants during validation catches things a single set of eyes will miss.

Failure mode

Field-type quirks

Certain project naming conventions get auto-interpreted by Vantagepoint as date values rather than text, which breaks the ability to drill into that field when grouping. It presents as “this isn’t a valid date” even though the field is a project name. The fix — using double forward slashes within the naming convention — was found only through direct trial and error, not documentation.

The throughline: this pattern removes VP’s native limitations, but it also removes VP’s native guardrails. Validation isn’t a final step — it’s a parallel activity throughout the build.

Track Record

As of July 2026

Complete
3
In progress
3
Expected complete ~mid-August 2026
  • complete Time-snapshot Backlog trending at Task level, 250-person AEC firm
  • complete Time-snapshot Backlog trending, cross-hub extension, same firm
  • complete Time-snapshot Backlog trending, separate engagement, AEC firm
  • in progress Time-snapshot WIP trending for quarterly/monthly billing review
  • in progress WBS-aggregation Project completion progress visualized at lower WBS levels
  • in progress WBS/AR merging AR detail data with lower WBS level information - Deltek joins incorrect sublevel data in dashparts

6 engagements total once the in-progress 3 close out. Having a repeatable sequence — rather than solving each one from scratch — has meaningfully sped up development on each subsequent build. The in-progress engagements are moving faster than the earlier ones did, as a direct result.

Why It Matters

The differentiator isn’t the profiler technique itself. It’s the recognition that several client requests that looked unrelated on the surface were actually the same underlying architecture problem wearing different clothes.

Turning that recognition into a repeatable sequence — with a known decision process, known table joins, and known design constraints — is the difference between being good at solving one-off technical problems and building a framework that gets faster and more reliable every time it’s used.

That’s the case for this kind of work specifically: not just closing gaps, but noticing when a gap is actually a category, and building the reusable answer once.