Skip to content
Saad Sultan
Back to Projects

Pipeline Status Configuration

Every team wants their own funnel. Making pipeline stages configurable without breaking automation or permissions.

Overview

I built the configurable pipeline feature for an applicant tracking product. Instead of a fixed set of stages, recruiters could define their own (e.g. Applied, Phone Screen, Technical, Offer). Each stage had a key and display name; moving a candidate from one stage to another was an explicit action that emitted events and enforced permissions. The backend stored pipeline config per tenant and candidate status history so we could report on funnel drop-off and stage duration.

Tech Stack

TypeScriptNode.jsMongoDBReactAnt Design

Impact & Scale

  • Recruiters tailor pipeline stages to their process without code changes
  • Status transitions trigger consistent events for analytics and integrations
  • Role-based rules control who can move candidates between stages

Key Challenges & Solutions

Keeping config and behaviour in sync

Adding or reordering stages had to work with existing candidates and with automation (e.g. "when assessment completed, move to Interview"). We stored a stable stage key and allowed display names and order to change so that automation and history did not break when recruiters edited the pipeline.

Events without coupling

Other parts of the product (analytics, webhooks, email triggers) needed to react to status changes. We emitted a single "candidate.stage_changed" event with old and new stage; subscribers could filter and act without the pipeline module knowing about them.

Permissions and bulk actions

Only certain roles could move candidates to certain stages (e.g. Offer). We enforced this in the API and in the UI so bulk "move to Offer" only showed and applied for users with permission, and the backend rejected unauthorised moves with a clear error.

Technical Highlights

  • Pipeline and stage model stored per tenant with keys, labels, and order
  • Candidate status history with timestamps and optional notes for audit and reporting
  • Event emission on stage change for analytics, webhooks, and internal automation
  • Permission checks on move actions; UI reflects allowed transitions per role
  • Settings UI for editing pipeline stages; candidate list and detail use configured stages for filters and actions

Role and scope

I designed and implemented the pipeline data model, the API for updating pipeline config and moving candidates, and the event emission. I also built the settings screen for pipeline editing and wired the candidate list and detail views to use the configured stages and permissions.

Architecture

Pipeline config lives in the tenant document or a dedicated collection; candidates reference stage by key. The move API validates the transition, checks permissions, updates the candidate, appends to status history, and emits an event. The frontend loads pipeline config once and uses it for filters, dropdowns, and bulk actions so the UI always matches what the backend allows.

Lessons learned

  • Stable keys, flexible labels. Stage keys should be immutable identifiers; labels and order can change so the product stays configurable without breaking automation or history.
  • One event, many subscribers. A single stage-change event kept the pipeline module simple and let analytics, webhooks, and email logic evolve independently.
  • Permissions at API and UI. Enforcing move permissions in the API prevented bypasses; reflecting them in the UI (e.g. disabling or hiding actions) made the product feel consistent and reduced support questions.

Interested in discussing this project or working together? Get in touch.