offdataai
HR & People · data model template

Recruiting / ATS data model

Normalized (3NF) recruiting/ATS model. Requisition and job backbone, candidate sourcing, application pipeline with explicit stage history, panel interviews with per-interviewer feedback, assessments, and offers. Candidate PII carries GDPR classification, consent, and retention-expiry handling.

Applicant-tracking operations: requisitions against jobs, candidates and their sourcing channels, applications moving through pipeline stages, interviews with panelists, assessments, and offers. Candidate PII is classified for GDPR with consent and retention controls. It is a normalized (3NF) relational model that mirrors the source system, suited to operational databases and to landing source data faithfully.

3NFHR & PeopleGDPREEOC
13
tables
107
columns
14
relationships
9
PII columns

Opening the template creates a project with the ERD, platform-native DDL, a dbt project and documentation already generated (recommended platform: PostgreSQL). Edit it in plain English or on the canvas, then ship it to any supported warehouse.

Subject areas

openingscandidatesevaluationoffers

Design decisions

  • Application as the join of candidate and requisition

    A candidate may apply to many requisitions; modeling the application as its own entity (rather than a column on candidate) lets pipeline state, interviews, assessments, and offers hang off the right grain.

  • Explicit stage-history table

    Pipeline conversion analytics (time-in-stage, drop-off) require the full transition log, not just the current stage; a history table keeps the application row 3NF while preserving the audit trail.

  • Panel interviews via interview/interviewer junction

    Multiple interviewers assess one interview and one interviewer works many interviews; the panelist junction carries per-reviewer scores and feedback without M:N duplication.

  • Candidate PII with consent and retention

    Resume is restricted+full-masked, contact fields partially masked; consent and retention-expiry fields support GDPR right-to-erasure and storage-limitation obligations.

Tables in the Recruiting / ATS model

Every table with its grain, columns, types and keys. PK marks a primary key, BK a business key and PII a column classified as personal data, which gets a masking strategy by default.

Tables (11)

department

Grain: one row per hiring department

ColumnTypeKeys
department_keybigintPK
department_codevarcharBK
department_namevarchar
cost_centervarchar

job

Grain: one row per job profile being recruited for

ColumnTypeKeys
job_keybigintPK
department_keybigint
job_codevarcharBK
job_titlevarchar
job_familyvarchar
seniority_levelvarchar
employment_typevarchar
locationvarchar
is_remoteboolean

requisition

Grain: one row per open requisition (a hiring need)

ColumnTypeKeys
requisition_keybigintPK
job_keybigint
requisition_numbervarcharBK
openingssmallint
statusvarchar
hiring_manager_idvarchar
recruiter_idvarchar
priorityvarchar
opened_datedate
target_fill_datedate
filled_datedate

candidate

Grain: one row per candidate (person)

Candidate PII classified for GDPR with consent + retention.

ColumnTypeKeys
candidate_keybigintPK
source_keybigint
candidate_external_idvarcharBK
first_namevarcharPII
last_namevarcharPII
emailvarcharPII
phonevarcharPII
locationvarcharPII
linkedin_urlvarcharPII
current_employervarchar
current_titlevarchar
resume_urlvarcharPII
consent_to_storeboolean
retention_expiry_datedate
created_attimestamp

application

Grain: one row per candidate application to a requisition

ColumnTypeKeys
application_keybigintPK
candidate_keybigint
requisition_keybigint
current_stage_keybigint
application_numbervarcharBK
statusvarchar
rejection_reasonvarchar
applied_attimestamp
decided_attimestamp

application_stage_history

Grain: one row per stage transition for an application

ColumnTypeKeys
application_stage_history_keybigintPK
application_keybigint
stage_keybigint
entered_attimestamp
exited_attimestamp
moved_by_user_idvarchar

interviewer

Grain: one row per employee who conducts interviews

Interviewer PII classified for GDPR.

ColumnTypeKeys
interviewer_keybigintPK
interviewer_external_idvarcharBK
full_namevarcharPII
emailvarcharPII
departmentvarchar
is_trainedboolean

interview

Grain: one row per scheduled interview for an application

ColumnTypeKeys
interview_keybigintPK
application_keybigint
stage_keybigint
interview_roundsmallint
interview_typevarchar
scheduled_attimestamp
duration_minutessmallint
statusvarchar
overall_recommendationvarchar

interview_panelist

Grain: one row per interviewer on an interview (junction) with feedback

ColumnTypeKeys
interview_panelist_keybigintPK
interview_keybigint
interviewer_keybigint
role_in_panelvarchar
scoredecimal
recommendationvarchar
feedbackvarchar
submitted_attimestamp

assessment

Grain: one row per assessment/test taken by an application

ColumnTypeKeys
assessment_keybigintPK
application_keybigint
assessment_namevarchar
assessment_typevarchar
providervarchar
scoredecimal
max_scoredecimal
passedboolean
completed_attimestamp

offer

Grain: one row per offer extended for an application

ColumnTypeKeys
offer_keybigintPK
application_keybigint
offer_numbervarcharBK
statusvarchar
base_salarydecimal
currency_codevarchar
bonus_amountdecimal
equity_unitsdecimal
start_datedate
extended_attimestamp
responded_attimestamp

Lookup tables (2)

source

Grain: reference list of candidate sourcing channels

ColumnTypeKeys
source_keybigintPK
source_codevarcharBK
source_namevarchar
source_typevarchar
cost_per_hiredecimal

stage

Grain: reference list of pipeline stages

ColumnTypeKeys
stage_keybigintPK
stage_codevarcharBK
stage_namevarchar
stage_ordersmallint
is_terminalboolean

Relationships

Each relationship is a foreign key on the first table referencing the second.

  • job.department_key → department (many-to-one)
  • requisition.job_key → job (many-to-one)
  • candidate.source_key → source (many-to-one)
  • application.candidate_key → candidate (many-to-one)
  • application.requisition_key → requisition (many-to-one)
  • application.current_stage_key → stage (many-to-one)
  • application_stage_history.application_key → application (many-to-one)
  • application_stage_history.stage_key → stage (many-to-one)
  • interview.application_key → application (many-to-one)
  • interview.stage_key → stage (many-to-one)
  • interview_panelist.interview_key → interview (many-to-one)
  • interview_panelist.interviewer_key → interviewer (many-to-one)
  • assessment.application_key → application (many-to-one)
  • offer.application_key → application (many-to-one)

Related templates

All templates →
Start for $1

From requirements to AI-ready context, in one platform.

Describe your business in a conversation, start from a template or connect your own database. Your first model is ready in minutes.

Get startedBook a demo

Plans from $1/month · cancel any time