Data Engineering Proof of Concept Scoping: A 4-Week Vendor PoC Playbook (2026)

By Peter Korpak · Chief Analyst & Founder Verified Jun 12, 2026
data engineering proof of concept scoping data engineering poc vendor pilot proof of concept paid pilot rfp
Data Engineering Proof of Concept Scoping: A 4-Week Vendor PoC Playbook (2026)

The conversation about proof of concepts in data engineering has matured in 2026. Buyers who ran free two-week PoCs in 2022 are now dealing with the consequences: pre-sales architects who disappeared at contract signature, codebases that looked good in the demo but collapsed under the first production load, and discovery calls that somehow never led to a written scope.

A data engineering proof of concept is not a feasibility study. It is risk management — for both sides. Done well, a PoC de-risks a $250k–$2M engagement before you commit. Done badly, it wastes a month, poisons the internal sponsor relationship, and gives you false confidence in a vendor you’ll regret hiring.

This playbook gives you the scope template, the code assets, the acceptance criteria framework, the IP clauses, and the go/no-go rubric you need to run a 4-week vendor-led PoC that actually answers the question you’re asking.

Why most data engineering proof-of-concept projects fail to convert

Most PoCs that don’t lead to a contract fall into one of three failure archetypes.

Archetype 1: Too narrow to prove anything. The vendor builds a pipeline on clean, synthetic data that looks nothing like your production systems. The Snowflake query runs fast because it’s hitting 50k rows. The dbt model looks elegant because the source schema is already normalized. You learn that the vendor can write SQL. You don’t learn whether they can handle your 40-column flat file from a 15-year-old ERP with inconsistent null handling.

Archetype 2: Too broad to finish in 4 weeks. The scope keeps growing — one more source, one more dashboard, one more stakeholder’s use case. The vendor is eager to please. Your team keeps adding requirements. Week 4 arrives and you have a half-built pipeline, three different architectural approaches, and no clear signal on whether you have a partner or a vendor.

Archetype 3: No kill-switch. There’s no written exit condition. Nobody defined what “success” looks like before the work started. At week 4, the vendor argues the pipeline is production-ready. Your engineers say it isn’t. You have no scoring rubric, no acceptance criteria, no documented decision framework. The relationship strains. The contract either gets signed under social pressure or collapses entirely — neither outcome reflects the actual technical picture.

The thesis of this guide: a PoC is a time-boxed risk instrument, not a sampler platter. Scope it before you start, define the kill-switch before you start, and pay for it. If you want a free PoC, you’re paying in a different currency — you’re paying with the pre-sales architect’s time, which means you’re getting pre-sales quality code.

Should you run a PoC at all?

Not every data engineering engagement needs a PoC. Run one when the contract value and technical risk justify the overhead. Here’s the decision logic:

Is the projected full contract value > $250k?
├── No → Skip PoC. Run a paid discovery sprint instead.
└── Yes
    └── Is this a net-new platform (not a like-for-like migration)?
        ├── No (like-for-like migration) → Is the vendor in your reference network?
        │   ├── Yes → PoC optional. Deep reference check may suffice.
        │   └── No → PoC recommended.
        └── Yes (net-new platform)
            └── Does your team have capacity for an 11-day go/no-go review?
                ├── No → PoC optional. Run discovery sprint + scorecard instead.
                └── Yes → PoC required.
Contract > $250k? No Skip — paid discovery sprint Yes Net-new platform? No Vendor in network? PoC optional (ref check may suffice) Yes Team has 11-day review capacity? No PoC optional (scorecard route) Yes PoC required Decision gate Terminal — skip Optional Required

If your project is a $400k migration from Redshift to Snowflake and the vendor has three referenceable clients in your industry, you may get more signal from two strong reference calls and a deep technical scorecard review than from a PoC. The PoC adds value when the technical risk is genuinely uncertain — new platform, new architectural pattern, vendor you haven’t worked with.

What is the right scope size for a data engineering PoC?

The Goldilocks problem in PoC scoping is real. Vendors tend to propose scopes that are easy to win — clean sources, simple transformations, no edge cases. Buyers tend to ask for too much — every data domain, every pipeline pattern, the full migration — which makes the PoC undeliverable in four weeks.

The right scope follows what Drexus calls the “80/20 rule”: pick the 20% of your data that is representative of 80% of the hard problems. This is not the easiest source and not the hardest. It is a single, realistic slice that exercises the architectural pattern you’re evaluating.

A well-scoped PoC covers exactly this:

  • 1–2 real source systems — not synthetic data, not a CSV export they cleaned. Real source credentials or at minimum a copy of a real table with production-representative dirty data.
  • 1 bronze table — raw ingest, no transformation, schema-on-write.
  • 1 silver table — cleaned, typed, deduplicated, with documented business rules.
  • dbt tests — not-null, accepted-values, uniqueness on the silver layer at minimum.
  • CI/CD deployment — the pipeline runs on merge, not just on the vendor’s laptop.

That’s it. A PoC that covers this slice in 4 weeks tells you: can this vendor design a schema, write clean SQL, instrument tests, automate deployment, and ship working code? Those five things predict production delivery quality better than any reference call.

What a PoC should not include: your hardest source (save that for Week 6 of the real project), dashboards or BI layer (that’s a different vendor selection problem), data governance setup, or more than one data domain.

One 2026-specific note: if your full project will run on Snowflake Cortex or Databricks Mosaic AI — not just “a data warehouse” — the PoC must include a slice on that specific platform. Vendors who demo on “whichever cloud you prefer” and then propose to bring in a different platform at contract signature are running a bait-and-switch. Make the platform explicit in the PoC scope document.

The 4-week PoC scope template

This is the deliverable that changes how you run the conversation with vendors. Use it verbatim or adapt it. The goal is that both sides sign the same document before a line of code is written.

Week 1: Discovery and environment setup

DayDeliverableOwner
1–2Data source inventory — table names, row counts, schema, sample of dirty recordsJoint
2–3Source system access confirmed (VPN, credentials, read-only service account)Buyer
3–4Dev environment provisioned (Snowflake trial account / dev workspace, git repo, CI runner)Vendor
4–5PoC architecture decision record (ADR) — medallion layers, naming conventions, orchestrator choiceVendor, buyer review

Acceptance gate: by end of day 5, the vendor has access to real source data and a working dev environment. If they don’t, the PoC is already at risk.

Week 2: Build — ingestion and silver layer

DayDeliverableOwner
6–7Bronze table loaded from Source 1 — raw ingest, append-only, no transformationVendor
7–8Silver table built from bronze — typed columns, dedup logic, null handling, documented business rulesVendor
8–9dbt sources.yml + schema.yml with not-null, unique, accepted-values tests — all passingVendor
9–10PR opened, code review requested from buyer’s engineerBoth

Week 3: Harden — CI/CD and second source

DayDeliverableOwner
11–12GitHub Actions CI pipeline — dbt lint, compile, test on every PRVendor
12–13Bronze table loaded from Source 2Vendor
13–14Observability stub — at minimum, row-count alerts on each layerVendor
14–15End-to-end run documented in README — one command to reproduce from scratchVendor

Week 4: Demo and decision

DayDeliverableOwner
16–17UAT walkthrough — buyer’s engineer runs the pipeline independently, not via vendor screen shareBuyer lead
17–18Code review complete — findings documentedBoth
19–20Final demo — walkthrough of architecture, tests, CI pipelineVendor
2011-day go/no-go scoring submitted by buyer teamBuyer

Code asset 1: Bronze-to-silver DDL and transformation (Snowflake)

-- =============================================================
-- PoC: orders pipeline  |  bronze → silver layer
-- Platform: Snowflake (Snowflake SQL)
-- BigQuery equivalent: PARTITION BY ingestion_date, use MERGE
-- Databricks equivalent: USING DELTA, MERGE INTO silver.orders
-- =============================================================

-- -------------------------------------------------------
-- 1. Bronze table — raw ingest, append-only, no transforms
-- -------------------------------------------------------
CREATE TABLE IF NOT EXISTS raw.orders_bronze (
    _raw_payload      VARIANT,           -- full source JSON blob
    _source_file      VARCHAR(512),      -- file name or stream ID
    _ingested_at      TIMESTAMP_NTZ DEFAULT CURRENT_TIMESTAMP(),
    _batch_id         VARCHAR(64)        -- idempotency key from pipeline run
);

-- -------------------------------------------------------
-- 2. Silver table — cleaned, typed, business rules applied
-- -------------------------------------------------------
CREATE TABLE IF NOT EXISTS curated.orders_silver (
    order_id          VARCHAR(36)     NOT NULL,
    customer_id       VARCHAR(36)     NOT NULL,
    order_date        DATE            NOT NULL,
    order_status      VARCHAR(32)     NOT NULL,   -- 'pending','processing','shipped','cancelled'
    line_item_count   INTEGER,
    gross_amount_usd  NUMERIC(18, 2),
    currency_code     CHAR(3)         NOT NULL,
    is_cancelled      BOOLEAN         NOT NULL DEFAULT FALSE,
    _source_file      VARCHAR(512),
    _ingested_at      TIMESTAMP_NTZ,
    _transformed_at   TIMESTAMP_NTZ   DEFAULT CURRENT_TIMESTAMP(),
    CONSTRAINT orders_silver_pk PRIMARY KEY (order_id)
);

-- -------------------------------------------------------
-- 3. Incremental merge: bronze → silver
-- Run daily by Airflow / dbt run-operation / Prefect task
-- -------------------------------------------------------
MERGE INTO curated.orders_silver AS tgt
USING (
    SELECT DISTINCT
        _raw_payload:order_id::VARCHAR(36)                                   AS order_id,
        _raw_payload:customer_id::VARCHAR(36)                                AS customer_id,
        TRY_TO_DATE(_raw_payload:order_date::VARCHAR, 'YYYY-MM-DD')          AS order_date,
        UPPER(TRIM(_raw_payload:status::VARCHAR))                            AS order_status,
        COALESCE(_raw_payload:line_items::ARRAY, ARRAY_CONSTRUCT())::VARIANT AS _line_items,
        ARRAY_SIZE(COALESCE(_raw_payload:line_items, ARRAY_CONSTRUCT()))     AS line_item_count,
        TRY_TO_DECIMAL(_raw_payload:gross_amount::VARCHAR, 18, 2)            AS gross_amount_usd,
        UPPER(COALESCE(_raw_payload:currency_code::VARCHAR, 'USD'))          AS currency_code,
        CASE WHEN UPPER(TRIM(_raw_payload:status::VARCHAR)) = 'CANCELLED'
             THEN TRUE ELSE FALSE END                                        AS is_cancelled,
        _source_file,
        _ingested_at
    FROM raw.orders_bronze
    -- Only process rows not yet in silver (incremental)
    WHERE _batch_id NOT IN (
        SELECT DISTINCT _source_file FROM curated.orders_silver
    )
      AND _raw_payload:order_id IS NOT NULL  -- hard guard: skip malformed rows
) AS src
ON tgt.order_id = src.order_id

WHEN MATCHED AND src._ingested_at > tgt._ingested_at THEN
    UPDATE SET
        order_status    = src.order_status,
        is_cancelled    = src.is_cancelled,
        _ingested_at    = src._ingested_at,
        _transformed_at = CURRENT_TIMESTAMP()

WHEN NOT MATCHED THEN
    INSERT (
        order_id, customer_id, order_date, order_status,
        line_item_count, gross_amount_usd, currency_code,
        is_cancelled, _source_file, _ingested_at
    )
    VALUES (
        src.order_id, src.customer_id, src.order_date, src.order_status,
        src.line_item_count, src.gross_amount_usd, src.currency_code,
        src.is_cancelled, src._source_file, src._ingested_at
    );

Code asset 2: dbt sources.yml + schema.yml

This is what the vendor should deliver by end of Week 2. If the test section is absent or has only a not_null on the primary key, that is a signal about the vendor’s production discipline. See dbt docs: sources for the full specification.

# models/staging/orders/_sources.yml
# -----------------------------------------------------------------
# Declares the raw bronze layer as a dbt source.
# Freshness check: alert if source not updated in 25 hours.
# -----------------------------------------------------------------
version: 2

sources:
  - name: raw_orders
    description: "Raw order events landed by the ingestion pipeline."
    database: "{{ env_var('DBT_DATABASE', 'POC_DB') }}"
    schema: raw
    loader: "airflow_gcs_load"
    freshness:
      warn_after: {count: 25, period: hour}
      error_after: {count: 48, period: hour}
    loaded_at_field: _ingested_at

    tables:
      - name: orders_bronze
        description: "Append-only raw ingest table. One row per source event."
        columns:
          - name: _batch_id
            description: "Idempotency key from pipeline run."
          - name: _ingested_at
            description: "Wall-clock timestamp when row landed in Snowflake."

# models/staging/orders/schema.yml
# -----------------------------------------------------------------
# Contract for the silver staging model.
# All tests must pass before a PR can merge (enforced by CI).
# -----------------------------------------------------------------
version: 2

models:
  - name: stg_orders
    description: >
      Cleaned, typed orders from the bronze layer.
      One row per order_id. Duplicate source records are deduplicated
      by taking the row with the latest _ingested_at.
    config:
      materialized: incremental
      unique_key: order_id
      on_schema_change: fail

    columns:
      - name: order_id
        description: "Source system order UUID."
        tests:
          - not_null
          - unique

      - name: customer_id
        description: "FK to customers domain."
        tests:
          - not_null

      - name: order_date
        description: "Date the order was placed (source timezone)."
        tests:
          - not_null

      - name: order_status
        description: "Normalised uppercase status string."
        tests:
          - not_null
          - accepted_values:
              values: ['PENDING', 'PROCESSING', 'SHIPPED', 'CANCELLED']
              severity: error

      - name: currency_code
        tests:
          - not_null
          - accepted_values:
              values: ['USD', 'EUR', 'GBP', 'CAD', 'AUD']
              severity: warn   # warn only — expand list in week 3

      - name: gross_amount_usd
        description: "Pre-tax order value in USD. NULL only for cancelled orders."

Code asset 3: GitHub Actions CI for dbt on PR

Every PR that touches models/ or dbt_project.yml should run this. If the vendor’s repo doesn’t have this file, ask why. See dbt’s recommended CI setup for the slim-CI variant that only runs changed models.

# .github/workflows/dbt-ci.yml
# -----------------------------------------------------------------
# Triggers on every PR targeting main.
# Runs: sqlfluff lint → dbt deps → dbt compile → dbt test (staging)
# Required secrets: DBT_PROFILES_YML (base64-encoded profiles.yml)
# -----------------------------------------------------------------
name: dbt CI

on:
  pull_request:
    branches: [main]
    paths:
      - "models/**"
      - "macros/**"
      - "dbt_project.yml"
      - "packages.yml"

env:
  DBT_PROFILES_DIR: /home/runner/.dbt
  DBT_TARGET: ci

jobs:
  dbt-ci:
    runs-on: ubuntu-latest
    timeout-minutes: 20

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Python 3.11
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
          cache: pip

      - name: Install dependencies
        run: |
          pip install --upgrade pip
          pip install dbt-snowflake==1.8.* sqlfluff sqlfluff-templater-dbt

      - name: Write dbt profiles
        run: |
          mkdir -p /home/runner/.dbt
          echo "${{ secrets.DBT_PROFILES_YML }}" | base64 -d > /home/runner/.dbt/profiles.yml

      - name: dbt deps
        run: dbt deps

      - name: sqlfluff lint
        run: |
          sqlfluff lint models/ \
            --dialect snowflake \
            --templater dbt \
            --config .sqlfluff \
            --format github-annotation \
            --annotation-level warning
        continue-on-error: false

      - name: dbt compile
        run: dbt compile --target ci

      - name: dbt test — staging layer only
        run: |
          dbt test \
            --select staging \
            --target ci \
            --store-failures \
            --vars '{"is_ci_run": true}'

      - name: Upload dbt artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: dbt-ci-artifacts
          path: |
            target/run_results.json
            target/manifest.json
          retention-days: 7

What every 4-week data engineering PoC scope must contain (15 items)

  1. Named source systems with real credentials or a production-representative sample
  2. Explicit platform — not “cloud data warehouse” but “Snowflake Enterprise on AWS us-east-1”
  3. Bronze table DDL with append-only ingest, batch ID, and ingestion timestamp
  4. Silver table DDL with typed columns, business rule documentation, and primary key constraint
  5. dbt sources.yml with freshness checks configured
  6. dbt schema.yml with at minimum: not-null, unique, and accepted-values tests on critical columns
  7. Incremental merge logic (not full-refresh) for the silver layer
  8. CI pipeline that blocks merge on failing dbt tests
  9. sqlfluff or equivalent linting enforced in CI
  10. End-to-end README: one command to reproduce the pipeline from scratch
  11. Observability stub: row-count alert on bronze and silver layers
  12. Architecture decision record (ADR) covering platform, orchestrator, and naming conventions
  13. IP transfer clause signed before Week 1 begins
  14. Kill-switch clause with objective exit conditions
  15. 11-day go/no-go scoring rubric agreed in writing before the PoC starts

How do you write SMART acceptance criteria for a data engineering PoC?

The acceptance criteria section is where most PoC documents fail. Buyers write criteria that sound rigorous but contain no measurable exit condition. Vendors accept them because vague criteria are easy to argue past.

SMART criteria for a PoC: Specific (one thing, not a category), Measurable (a number or binary pass/fail), Achievable (within the PoC scope, not the full project), Relevant (tests what you actually care about in production), Time-bound (passes by end of which week).

Bad criteriaSMART version
”Pipeline handles real data”Bronze table loaded from Source 1 contains ≥ 10,000 rows matching row count in source system ± 0.1%, verified by buyer’s engineer running SELECT COUNT(*) independently
”dbt models are well-tested”All models in models/staging/ have at minimum not-null + unique tests on primary key columns; dbt test exits with code 0 in CI on every PR
”Code is maintainable”sqlfluff lint score ≤ 2 violations per 100 lines on models/ directory, enforced by CI; all violations are warning-level, none are error-level
”Pipeline runs automatically”GitHub Actions CI workflow triggers on PR open and completes in ≤ 15 minutes; dbt test step must pass before merge is permitted
”Data quality is acceptable”Silver table is_cancelled flag matches source system cancellation count within ±5 records for the 30-day sample period provided by buyer
”Vendor communicates well”Vendor provides written status update by 17:00 on each working day during the PoC; no unresolved blocking issue goes unacknowledged for more than 4 business hours
”Architecture is documented”Architecture decision record (ADR) delivered by end of Week 1; covers platform choice, orchestrator, layer naming, and incremental strategy
”Pipeline is observable”Row-count alert configured on bronze and silver tables; fires a Slack/Teams notification when current batch row count deviates > 20% from 7-day rolling average

Write these into the PoC scope document, not the final SOW. The PoC scope document is its own agreement. For the full SOW acceptance criteria pattern that follows a successful PoC, see the data engineering statement of work guide.

PoC pricing models: paid, credit-forward, success-based

Free PoCs are not free. They’re funded by the vendor’s pre-sales budget, which means they’re staffed by pre-sales people. The engineer who writes your Week 2 silver table is not the engineer who will own your production pipeline. In 2026, buyers who have learned this lesson are budgeting for paid pilots as a line item.

ModelWhen to useBuyer costBuyer protectionRisk
Paid flat-feeDefault. Any project > $250k with net-new platform.$8k–$25k for 4 weeks, depending on vendor size and scope complexityIP transfers regardless of outcome; vendor fields their best engineer, not pre-salesBuyer pays even if PoC fails — mitigated by kill-switch clause
Credit-forwardVendor applies PoC fee as a credit toward full contract. Most vendors will offer this.$0 net if contract signed; otherwise pays full PoC feeSame as paid — IP transfers, senior staffingIf PoC succeeds and you choose a different vendor, you pay the full PoC fee; plan for this
Success-basedHigh-trust situations where both sides are already confident — PoC is more due diligence than a real risk gate$0 if PoC fails; 10–15% premium on full contract if signedWeakest — vendor incentivized to hit a binary threshold, not build the best possible scopeVendor may game the acceptance criteria; avoid unless relationship already established

The default recommendation is paid + credit-forward. Pay a flat $10k–$18k. Negotiate credit-forward as a term. Get IP transfer in writing. This model aligns incentives: the vendor fields real engineers (not pre-sales), and the buyer has skin in the game (no PoC fishing expedition). Both sides are motivated to make the 4 weeks productive.

The 11-day go/no-go scoring rubric

On day 20 (or equivalent end of PoC), the buyer team — data engineering lead, IT lead, and one business stakeholder — each complete this independently. Aggregate the scores. Do not discuss until everyone has submitted.

DimensionWhat to score 1–5Weight
Technical deliveryAll Week 2 and Week 3 deliverables met on schedule? Bronze + silver tables working? CI pipeline live?35%
Code qualityIs the SQL clean, commented, and following agreed conventions? Are dbt tests meaningful (not just not-null on PK)? Does the README reproduce the pipeline?25%
CommunicationDid the vendor send daily status updates? Were blockers surfaced early? Were questions answered within 4 hours?20%
Problem-solvingWhen a source schema had an unexpected issue (and one always does), how did the vendor respond? Did they fix it or escalate and wait?15%
VelocityDid the vendor maintain pace? Were Week 3 hardening tasks treated as real requirements or optional extras?5%

Decision rules:

  • Weighted score ≥ 4.2 with no single dimension below 3.5 → Proceed. Move directly to SOW negotiation.
  • Weighted score 3.5–4.1 → Proceed with documented adjustments. Identify the weak dimension. Add a corresponding mitigation clause to the SOW (extra review gates, staffing commitment, etc.).
  • Any single dimension scored 1–2 by two or more scorers → No-go unless the dimension is velocity (weight 5%) and the cause is clearly explained and corrected.
  • Weighted score below 3.5 → No-go. Do not negotiate on sentiment. Use the rubric.

To build this rubric into your overall vendor selection framework, cross-reference the data engineering vendor evaluation criteria that applies to the full engagement, not just the PoC.

Who owns the code and IP from a PoC?

This is the clause buyers most often forget to include and vendors most often omit from their PoC agreement. Without it, you may have paid for 4 weeks of work that the vendor technically owns — and that they can, in theory, repurpose for another client.

Add this language verbatim to the PoC scope agreement, before Week 1 begins:

IP Transfer. All code, documentation, configuration files, data models, architecture decision records, and other artefacts created by Vendor during the Pilot Period (“Pilot Artefacts”) shall be owned exclusively by Client from the date of creation, regardless of whether the Pilot results in a subsequent engagement. Vendor assigns to Client all right, title, and interest in the Pilot Artefacts, including all intellectual property rights therein. Vendor retains no license to use, reproduce, or adapt the Pilot Artefacts for any third party without Client’s prior written consent.

Two additional clauses that belong in the same section:

Confidentiality. Vendor shall treat all source data, schema structures, row counts, and business rule documentation accessed during the Pilot as Client confidential information. This obligation survives termination of the Pilot for a period of five years.

No competitive use. Vendor shall not use Client’s data, pipeline patterns, or architectural decisions as a reference case, case study, or marketing asset without Client’s prior written consent.

If the vendor pushes back on the IP transfer clause, that is a signal worth investigating. Legitimate vendors — especially those who are confident in their delivery — have no reason to retain ownership of code written on your data.

What’s the right off-ramp clause if the PoC fails?

The kill-switch clause is short. Put it in the PoC scope agreement directly:

No-Go Exit. Either party may terminate the Pilot at the end of the Pilot Period (Day 20) by providing written notice within two business days of the Final Demo. In the event of a no-go decision: (a) Vendor shall deliver all Pilot Artefacts to Client within five business days; (b) no further payment obligations arise beyond fees already invoiced; (c) neither party shall have any obligation toward a subsequent engagement.

If you are using the credit-forward pricing model, add:

Credit-Forward Condition. The PoC fee credit applies only if Client enters into a subsequent data engineering engagement with Vendor within 90 days of Pilot completion. If Client does not proceed, the PoC fee is payable in full per the invoiced amount.

Do not add language that makes it difficult to exit. Language like “Buyer must provide written justification for no-go decision with specific deficiencies cited” is a trap — it hands the vendor leverage to dispute your rubric scores. The go/no-go rubric is your justification. Point to it.

Common scope-creep traps and how to head them off

These are the six patterns that reliably expand a 4-week PoC into a 9-week PoC.

“While we’re in there” additions. A stakeholder attends the Week 2 demo and asks for a third source. Fix: all scope changes require written amendment to the PoC scope document, approved by both sides, before any work begins.

Dashboard requests. Someone from the BI team asks for a Tableau / Looker / Power BI connection by Week 3. Fix: the PoC scope document explicitly lists “BI layer” as out of scope.

The platform migration mid-PoC. The vendor proposes switching from the agreed platform (“we think Databricks would actually be a better fit”) midway through Week 2. Fix: platform is locked in the PoC scope document. Any platform change requires a new PoC, not an extension.

Governance requirements added late. Legal or compliance asks for column-level masking and data lineage documentation in Week 3. Fix: governance requirements that affect the PoC architecture must be raised in Week 1 discovery. Post-Week-1 additions are deferred to the full SOW.

Vendor adds engineers without notice. The vendor introduces a junior developer in Week 3 without discussion. Fix: the PoC scope document names the vendor-side personnel. Personnel changes require written notice and buyer approval.

Extending the timeline rather than calling a no-go. The most expensive trap. The PoC slips past day 20 and everyone agrees informally to “just one more week.” Fix: the go/no-go scoring rubric is completed on day 20 regardless of completeness. An incomplete PoC is scored on what was delivered, not what was promised. Incompleteness is a signal, not a technicality.

AI coding agent opacity. In 2026, many vendor engineers use Cursor, Cody, or GitHub Copilot. That’s fine — the question is whether they use them with discipline (reviewing output, running tests, understanding what was generated) or as a black box (commit the generated code, move on). The PoC code review in Week 4 is when you find out. Ask directly: “Which parts of this codebase were AI-assisted? Walk me through how you reviewed the generated SQL.”

The “we need production data” demand. Vendor claims they can’t prove anything without full production access. Fix: a PoC requires a production-representative sample (≥ 10,000 rows, representative of the dirty-data patterns you actually have), not full production access. Prepare this sample in Week 1.

Frequently asked questions

How long should a data engineering proof of concept take?

Four weeks is the right size for a vendor-led data engineering PoC. Two weeks is too short to get past the dev environment setup and still build something meaningful. Eight weeks is long enough to become a mini-project, which defeats the purpose of risk management. The 4-week timeline — 1 week discovery, 2 weeks build, 1 week harden and demo — produces a deployable slice that answers the real question: can this vendor deliver production-quality code?

Should the PoC be paid or free?

Paid. The reasoning is not ideological — it’s about staffing. Vendors fund free PoCs from pre-sales budgets, which means the engineers you get during the PoC are not the engineers you’ll get after contract signature. A paid PoC — $8k–$25k depending on scope — forces the vendor to staff it from their delivery bench. That’s the team you’re actually evaluating. Negotiate a credit-forward clause so the PoC fee applies toward the full contract if you proceed.

Who should write the PoC scope — buyer or vendor?

The buyer should write the first draft. Vendors who write the PoC scope will, rationally, write a scope that plays to their strengths. Your first draft should specify: the real source systems, the platform, the acceptance criteria, the IP clause, and the go/no-go rubric. Then share it with the vendor and negotiate. The final signed document should be a joint agreement, but the buyer’s interests should be the structural foundation.

For the broader question of who drives the vendor selection process, see the RFP process best practices guide.

What if the PoC succeeds technically but the vendor felt wrong?

Score the communication and problem-solving dimensions honestly in the go/no-go rubric. “Felt wrong” usually means one of those dimensions scored low — slow responses, unclear status updates, a defensive reaction to code feedback. If the rubric surfaces a low communication or problem-solving score, that is a documented, defensible reason to consider alternatives even when the technical delivery was strong. Trust the rubric, not the sentiment. Then read the discovery call questions guide — if you’re having this feeling after the PoC, there were probably signals in the early conversations that got rationalized away.

Next step

The PoC is one stage in the full vendor selection sequence. Before you get here, you need a shortlist. After you pass the go/no-go gate, you need a contract.

For the shortlist, the data engineering partner selection hub maps the full process. For common mistakes that push PoCs in the wrong direction before they start, see RFP mistakes in data engineering.

When the PoC passes and you’re ready to draft the engagement contract, the data engineering statement of work guide covers the acceptance criteria, milestone payment structure, and SLA language that picks up where the PoC scope document ends.

If you want a pre-screened shortlist of vendors who have run structured PoCs before and have referenceable results, get matched or download the data engineering RFP checklist to use alongside this playbook.


Technical references: dbt documentation — sources, dbt CI best practices, Snowflake MERGE INTO syntax, Databricks Delta Lake MERGE.

Peter Korpak · Chief Analyst & Founder

Data-driven market researcher with 20+ years in market research and 10+ years helping software agencies and IT organizations make evidence-based decisions. Former market research analyst at Aviva Investors and Credit Suisse.

Previously: Aviva Investors · Credit Suisse · Brainhub · 100Signals

Related Analysis