twimco.Let’s talk ↗︎
Menu
Field notes / Buying software

CSV import is a product feature, not a favor

Someone always asks to "just upload a spreadsheet." If import is how real customers start—or how they recover—it needs validation, a dry run, and an owner, not a one-off engineer weekend.

Editorial engraving of a sunlit apparel studio where an operations manager holds a USB stick and blank spreadsheet template beside a pattern maker reviewing a dry-run printout.

Treat CSV or spreadsheet import as a first-class feature when it is part of onboarding, migration, or recurring ops. Specify required columns, validation errors people can fix, a dry-run preview, idempotent re-uploads, and who supports bad files. If import is only a side promise in a sales call, either build it properly or take it out of the proposal.

When import is the product

Walk a new customer into your web app. If their first useful day requires moving hundreds of rows from Excel—SKUs, members, locations, price lists—then CSV import is not a courtesy. It is onboarding. The same is true when ops re-imports weekly from a partner. A spreadsheet upload without validation is a support queue in disguise.

Our earlier note that your spreadsheet is already software argued for respecting the sheet. This walk-through is about the upload door you build next to it.

How the work moves

CSV import path worth shipping

  1. Template

    Headers and one example row.

  2. Upload

    Type, size, encoding checks.

  3. Validate

    Row errors with fix hints.

  4. Dry run

    Create / update / skip / fail counts.

  5. Commit + receipt

    Idempotent write; summary and error CSV.

Illustrative product flow; not a client screenshot or measured result.

Walk the happy path as a specification

Write the path before anyone codes:

  1. Template. A downloadable CSV with required headers and one example row. No silent optional columns that change meaning.
  2. Upload. Size limit, encoding (UTF-8), and a clear reject if the file is not CSV/TSV.
  3. Validate. Row-level errors with the row number and a fix hint ("Column price must be a number").
  4. Dry run. Show counts: would create, would update, would skip, would fail. Nothing written yet.
  5. Commit. Idempotent on a business key (SKU, member id) so a second upload does not duplicate.
  6. Receipt. A summary the customer can save; failed rows downloadable as a CSV of errors.

If your proposal cannot afford that path, do not sell "we'll help you import." Sell a paid migration project with a named owner instead.

A spreadsheet upload without validation is a support queue in disguise.

Walk the failure path harder than the demo

Bad files are the real workload: merged cells exported wrong, dates in three formats, extra header rows, commas inside unquoted fields, duplicate keys, deleted columns mid-year. Decide which errors block the whole file and which isolate to a row. Decide who in support is allowed to re-run an import for a customer—and whether that person needs an audit log.

Security matters too: imports are a bulk write. Authz, virus scanning, and PII handling belong in the same design conversation as the UI.

Buying or building: questions for the vendor or the brief. - Is import in the product today, or a services SOW?

  • Which entities can be imported, and what is the uniqueness key?
  • Can we dry-run? Can we export the same shape we import?
  • What happens when row 4,002 fails?
  • Who supports the customer when the file is messy?

Put answers into the custom product build brief or the vendor scorecard. Ambiguity here becomes a week of Slack files named final_v7.csv.

Decision guide

Favor import vs productized import

ConsiderationOne-off favorProduct feature
OwnerEngineer weekend; no support path.Named product surface with docs.
ErrorsFails opaquely; Slack the file.Row-level messages and error export.
RerunDuplicates on second try.Idempotent on a business key.
SalesPromised in the demo.Listed in the contract with limits.
RiskBulk write without audit.Authz, logging, PII rules included.
Decision framework when buying or scoping software; illustrative only.

A concrete onboarding story

A composite B2B buyer arrives with 2,400 SKUs in a spreadsheet their ERP spat out. Sales promised "just upload your catalog." On kickoff week the engineer accepts a file over Slack, cleans it by hand, and loads production once. Two weeks later the buyer sends catalog_final_really.csv with new columns. Nobody remembers the mapping. Support cannot help. The buyer stalls.

Productized import would have given them a template matching your product model, rejected the unknown columns with reasons, previewed 2,400 updates, and left an audit of who committed the load. The Slack favor felt fast in week one and expensive by week three.

If you are mid-contract without import, be honest: offer a dated migration workshop with a sample file, a mapping sheet, and a single production load window—or accelerate the feature. Do not keep saying "upload anytime" into a void.

Recurring partner imports deserve scheduling and alerts when the file shape drifts. A silent schema change from a supplier is how bad prices and ghost SKUs enter the storefront. Validation that emailed a diff to ops yesterday is worth more than a dashboard nobody opens.

Operations after the first load

Imports do not end at onboarding. Partners send weekly inventory files. Franchise locations upload rosters. Finance drops price lists. Each recurring path needs a schedule, a failure alert, and a person who owns a bad file on Tuesday morning.

Version the template. When you add a required column, bump the template version in the header row and reject old files with a message that links to the new download. Silent acceptance of unknown columns is how mystery data enters production.

For large files, show progress and allow cancel. A browser tab that spins for ten minutes teaches people to upload twice. Idempotency saves you when they do anyway.

Log every commit with who, when, source filename, and counts. That log is the first thing you open when a customer says "your system changed our prices overnight." Without it, you are guessing between your app and their spreadsheet.

Put this into practice

We build web applications where bulk import is scoped like any other write path—validation, preview, audit. If your sales team is promising spreadsheet uploads your product cannot safely run, talk to us before the next kickoff.

One more buying tip: ask for a live import of your messy sample file during the vendor demo—not their perfect template. Watch how errors render. Watch whether the sales engineer quietly cleans the file off-screen. The messy file is the product. If they will not run it, believe that too.

When you build in-house, budget design time for the error CSV and the empty state when validation fails entirely. Those screens are where trust is won.

Permissions belong in the same design: who may import, into which workspace, and whether imports require a second approver above a row threshold. Bulk write is a privileged action. Treat it with the seriousness you already give to bulk delete and role changes.

Document the uniqueness key in the UI near the upload button—"Rows match on SKU; a second upload updates the same SKU." People guess wrong otherwise and create duplicates that take weeks to unwind.

For very large imports, consider an asynchronous job with an email when complete. Synchronous browser uploads time out and tempt double submits. The dry run should still be available before the job is queued.

Finally, tie import success to customer outcomes in onboarding checklists: "First catalog load complete with fewer than N error rows" is a better kickoff exit criterion than "credentials issued." Make the spreadsheet path visible in the project plan from day one.

Related work: PatientIQ.

twimco.

We build alongside the people doing the work.
Bring us the problem you’re thinking about.

Related work

PatientIQ ↗︎