LEHD J2J Flows
Job-to-job worker flows from the Census LEHD program: how workers move between employers, industries and regions.
lehd_j2j_flows — the dataset name to pass to the Obscura API.
What one row means
One national worker-reallocation statistic for the U.S. Census LEHD Job-to-Job (J2J) program: a single hire/separation/earnings flow measure (hires, separations, job-to-job transitions, nonemployment transitions, or earnings-linked variants) computed for one calendar quarter, crossed by one specific combination of demographic, industry, ownership, and firm dimensions (or their "all" marginal codes), all at the national geography level.
One row per (row_key) — a deterministic surrogate built from the 17 dimension columns (periodicity, seasonadj, geo_level, geography, ind_level, industry, ownercode, sex, agegrp, race, ethnicity, education, firmage, firmsize, year, quarter, agg_level).
Point-in-time availability
Every Obscura dataset carries available_date: the calendar day the publisher made the row
available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the
same thing on every dataset in the catalog.
For lehd_j2j_flows: published: available_date = period_end (last calendar day of the observation quarter) + 366 days, Census's documented J2J release lag.
Refresh cadence
Obscura refreshes lehd_j2j_flows daily — the most frequent scheduled job that re-collects or re-exports it. This is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when a row became public is recorded per row in available_date.
Schema — 90 columns
The full public column list for lehd_j2j_flows, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/lehd_j2j_flows.
| Column | Type | Description |
|---|---|---|
| row_key | text · not null | Deterministic surrogate key: every dimension column joined with `|`. |
| periodicity | text · not null | Time series periodicity, e.g. `Q` (quarterly). |
| seasonadj | text · not null | Seasonal-adjustment flag, e.g. `S` (seasonally adjusted) / `U`. |
| geo_level | text · not null | Geography level code, e.g. `N` (national). |
| geography | text · not null | Geography code (national = `00`). |
| ind_level | text · not null | Industry level code, e.g. `A` (all), `S` (sector). |
| industry | text · not null | Industry code (NAICS sector / `00` = all). |
| ownercode | text · not null | Ownership code, e.g. `A00`. |
| sex | text · not null | Sex code (`0` = all, `1` = male, `2` = female). |
| agegrp | text · not null | Age-group code, e.g. `A00` (all). |
| race | text · not null | Race code, e.g. `A0` (all). |
| ethnicity | text · not null | Ethnicity code, e.g. `A0` (all). |
| education | text · not null | Education code, e.g. `E0` (all). |
| firmage | text · not null | Firm-age code (`0` = all). |
| firmsize | text · not null | Firm-size code (`0` = all). |
| year | integer · not null | Calendar year of the observation quarter. |
| quarter | integer · not null | Calendar quarter (1-4) of the observation period. |
| agg_level | integer · not null | Aggregation-level bitmask indicating which dimensions are marginalized. |
| period_end | date · not null | Last calendar day of `(year, quarter)` — the real observation period end. |
| available_date | date · not null | PUBLIC-availability date = period_end + 366 days (Census's documented J2J release lag). DB-generated (STORED), read-only; the point-in-time column to filter/join on — NEVER the observation quarter's own period_end. |
| m_hire | double precision | Total hires ("M" margin measure) into jobs during the quarter — all new-job accessions regardless of the worker's prior employment status. |
| m_sep | double precision | Total separations from jobs during the quarter — all job endings regardless of the worker's subsequent employment status. |
| m_job_start | double precision | Count of jobs that started (first appear on payroll) during the quarter, a job-level companion measure to m_hire. |
| m_job_end | double precision | Count of jobs that ended during the quarter, a job-level companion measure to m_sep. |
| ee_hire | double precision | Employer-to-Employer hires: hires where the worker moved directly from another employer with no intervening quarter of nonemployment. |
| ee_sep | double precision | Employer-to-Employer separations: separations where the worker moved directly to another employer with no intervening nonemployment quarter. |
| aq_hire | double precision | Adjacent-quarter hires: hires where the worker was employed at a different employer in the immediately adjacent quarter, a broader job-to-job hire measure than ee_hire. |
| aq_sep | double precision | Adjacent-quarter separations: the corresponding separation-side counterpart to aq_hire. |
| j2j_hire | double precision | The published Job-to-Job hire flow — Census's headline job-to-job accession statistic combining the ee/aq methodology. |
| j2j_sep | double precision | The published Job-to-Job separation flow — Census's headline job-to-job separation statistic, counterpart to j2j_hire. |
| ne_hire | double precision | Nonemployment-to-Employment hires: hires where the worker was not employed anywhere in the prior quarter. |
| en_sep | double precision | Employment-to-Nonemployment separations: separations where the worker has no employer in the following quarter. |
| ne_persist | double precision | Nonemployment-to-Employment hires that persist — the subset of ne_hire where the worker remains employed at the same employer into the subsequent quarter. |
| en_persist | double precision | Employment-to-Nonemployment separations that persist — the subset of en_sep where the worker remains out of employment through the subsequent quarter. |
| ne_full_q | double precision | Nonemployment-to-Employment hires where the resulting job is a full-quarter job, a stricter subset of ne_hire. |
| en_full_q | double precision | Employment-to-Nonemployment separations preceded by a full-quarter job at the origin employer, the separation-side counterpart to ne_full_q. |
| main_b | double precision | Main-job stock count at the beginning of the quarter (a stock/levels measure, not a flow). |
| main_e | double precision | Main-job stock count at the end of the quarter, the same stock measure as main_b evaluated at period end. |
| ee_sep_s | double precision | "Stable" variant of ee_sep: employer-to-employer separations restricted to jobs meeting Census's stable/full-quarter tenure criterion. |
| ee_hire_s | double precision | "Stable" variant of ee_hire: employer-to-employer hires restricted to stable (tenure-qualifying) jobs. |
| aq_sep_s | double precision | "Stable" variant of aq_sep: adjacent-quarter separations restricted to stable jobs. |
| aq_hire_s | double precision | "Stable" variant of aq_hire: adjacent-quarter hires restricted to stable jobs. |
| ne_persist_s | double precision | "Stable" variant of ne_persist: nonemployment-to-employment hires that persist, restricted to stable jobs. |
| en_persist_s | double precision | "Stable" variant of en_persist: employment-to-nonemployment separations that persist, restricted to stable-job origins. |
| job_stay_s | double precision | Count of stable jobs where the worker stays with the same employer across the quarter boundary (job retention). |
| main_b_s | double precision | "Stable" variant of main_b: beginning-of-quarter main-job stock count restricted to stable jobs. |
| main_e_s | double precision | "Stable" variant of main_e: end-of-quarter main-job stock count restricted to stable jobs. |
| ne_hire_s_earn_dest | double precision | Earnings-linked stable variant of ne_hire, reported with the destination (new) job's earnings attached. |
| en_sep_s_earn_orig | double precision | Earnings-linked stable variant of en_sep, reported with the origin job's earnings attached. |
| job_stay_s_earn_orig | double precision | Earnings-linked stable job-stayer measure with the origin job's earnings attached (pre-transition/baseline earnings). |
| job_stay_s_earn_dest | double precision | Earnings-linked stable job-stayer measure with the destination-period earnings attached (post-period earnings for job stayers). |
| ee_sep_s_earn_orig | double precision | Earnings-linked stable variant of ee_sep, reported with the origin employer's earnings attached (pre-move earnings baseline). |
| ee_hire_s_earn_dest | double precision | Earnings-linked stable variant of ee_hire, reported with the destination employer's earnings attached (post-move earnings). |
| aq_sep_s_earn_orig | double precision | Earnings-linked stable variant of aq_sep, reported with the origin employer's earnings attached. |
| aq_hire_s_earn_dest | double precision | Earnings-linked stable variant of aq_hire, reported with the destination employer's earnings attached. |
| s_m_hire | integer | LEHD status flag for `m_hire` (raw `sMHire`). |
| s_m_sep | integer | LEHD status flag for `m_sep` (raw `sMSep`). |
| s_m_job_start | integer | LEHD status flag for `m_job_start` (raw `sMJobStart`). |
| s_m_job_end | integer | LEHD status flag for `m_job_end` (raw `sMJobEnd`). |
| s_ee_hire | integer | LEHD status flag for `ee_hire` (raw `sEEHire`). |
| s_ee_sep | integer | LEHD status flag for `ee_sep` (raw `sEESep`). |
| s_aq_hire | integer | LEHD status flag for `aq_hire` (raw `sAQHire`). |
| s_aq_sep | integer | LEHD status flag for `aq_sep` (raw `sAQSep`). |
| s_j2j_hire | integer | LEHD status flag for `j2j_hire` (raw `sJ2JHire`). |
| s_j2j_sep | integer | LEHD status flag for `j2j_sep` (raw `sJ2JSep`). |
| s_ne_hire | integer | LEHD status flag for `ne_hire` (raw `sNEHire`). |
| s_en_sep | integer | LEHD status flag for `en_sep` (raw `sENSep`). |
| s_ne_persist | integer | LEHD status flag for `ne_persist` (raw `sNEPersist`). |
| s_en_persist | integer | LEHD status flag for `en_persist` (raw `sENPersist`). |
| s_ne_full_q | integer | LEHD status flag for `ne_full_q` (raw `sNEFullQ`). |
| s_en_full_q | integer | LEHD status flag for `en_full_q` (raw `sENFullQ`). |
| s_main_b | integer | LEHD status flag for `main_b` (raw `sMainB`). |
| s_main_e | integer | LEHD status flag for `main_e` (raw `sMainE`). |
| s_ee_sep_s | integer | LEHD status flag for `ee_sep_s` (raw `sEESepS`). |
| s_ee_hire_s | integer | LEHD status flag for `ee_hire_s` (raw `sEEHireS`). |
| s_aq_sep_s | integer | LEHD status flag for `aq_sep_s` (raw `sAQSepS`). |
| s_aq_hire_s | integer | LEHD status flag for `aq_hire_s` (raw `sAQHireS`). |
| s_ne_persist_s | integer | LEHD status flag for `ne_persist_s` (raw `sNEPersistS`). |
| s_en_persist_s | integer | LEHD status flag for `en_persist_s` (raw `sENPersistS`). |
| s_job_stay_s | integer | LEHD status flag for `job_stay_s` (raw `sJobStayS`). |
| s_main_b_s | integer | LEHD status flag for `main_b_s` (raw `sMainBS`). |
| s_main_e_s | integer | LEHD status flag for `main_e_s` (raw `sMainES`). |
| s_ne_hire_s_earn_dest | integer | LEHD status flag for `ne_hire_s_earn_dest` (raw `sNEHireSEarn_Dest`). |
| s_en_sep_s_earn_orig | integer | LEHD status flag for `en_sep_s_earn_orig` (raw `sENSepSEarn_Orig`). |
| s_job_stay_s_earn_orig | integer | LEHD status flag for `job_stay_s_earn_orig` (raw `sJobStaySEarn_Orig`). |
| s_job_stay_s_earn_dest | integer | LEHD status flag for `job_stay_s_earn_dest` (raw `sJobStaySEarn_Dest`). |
| s_ee_sep_s_earn_orig | integer | LEHD status flag for `ee_sep_s_earn_orig` (raw `sEESepSEarn_Orig`). |
| s_ee_hire_s_earn_dest | integer | LEHD status flag for `ee_hire_s_earn_dest` (raw `sEEHireSEarn_Dest`). |
| s_aq_sep_s_earn_orig | integer | LEHD status flag for `aq_sep_s_earn_orig` (raw `sAQSepSEarn_Orig`). |
| s_aq_hire_s_earn_dest | integer | LEHD status flag for `aq_hire_s_earn_dest` (raw `sAQHireSEarn_Dest`). |
Access lehd_j2j_flows
Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.
import obscura
client = obscura.Client("obs_live_…")
df = client.query(
dataset="lehd_j2j_flows",
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the lehd_j2j_flows dataset?
Job-to-job worker flows from the Census LEHD program: how workers move between employers, industries and regions. One national worker-reallocation statistic for the U.S. Census LEHD Job-to-Job (J2J) program: a single hire/separation/earnings flow measure (hires, separations, job-to-job transitions, nonemployment transitions, or earnings-linked variants) computed for one calendar quarter, crossed by one specific combination of demographic, industry, ownership, and firm dimensions (or their "all" marginal codes), all at the national geography level.
How do I avoid look-ahead bias with lehd_j2j_flows?
Filter on lehd_j2j_flows.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — published: available_date = period_end (last calendar day of the observation quarter) + 366 days, Census's documented J2J release lag. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get lehd_j2j_flows?
As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="lehd_j2j_flows". The column schema is public at https://api.obscura.trade/v1/catalog/lehd_j2j_flows.
How often is lehd_j2j_flows updated?
Obscura refreshes lehd_j2j_flows on a daily schedule — that is the most frequent scheduled job that re-collects or re-exports the table. It is Obscura's own pipeline cadence, not the upstream publisher's release schedule; when the publisher makes a row available is described by the availability rule above, and is recorded per row in available_date.