Forecasting from a Government PDF: What I Learned Modeling the Visa Bulletin
DEV Community

Forecasting from a Government PDF: What I Learned Modeling the Visa Bulletin

Every month the U.S. State Department publishes the Visa Bulletin. If you have never had to read one, picture a set of grids: rows for green-card categories like EB-2 and EB-3, columns for a handful of countries, and inside each cell either a date or the letter "C" for current.

That date is the cutoff. If your priority date is earlier than the cutoff for your category and country, your case can move forward. If it isn't, you wait. It looks like structured data. It mostly isn't. And the moment you try to turn a year of these bulletins into anything a person can plan around, you run straight into the reason immigration timing feels so unknowable: the source is a monthly snapshot that was never designed to be a time series.

I spent a while building tooling around exactly this problem, and the interesting engineering was almost never where I expected it.

The parsing is annoying before it is hard

The bulletins are published as web pages and PDFs whose layout drifts over the years. Column headers get reworded. A country gets its own column one year and gets folded into "All Chargeability Areas Except Those Listed" another. Dates appear as 08JAN20, sometimes 01JANUARY2020, sometimes just C, and occasionally U for unavailable, which is a different thing from a date being blank.

None of that is intellectually deep. It is the ordinary tax of pulling a dataset out of documents meant for human eyes. The trap is treating it as a one-time scrape. Because the format shifts, a parser that passed on last year's files can silently mangle this month's, and a silent mangle in a forecast is worse than a crash.

So the real work is validation:

  • Range-check every parsed date.
  • Assert that categories that existed last month still exist.
  • Flag any cell that moved in a direction the rules say is unusual, so a human can look before it feeds anything downstream.

Movement is not a smooth signal

Once you have a clean series of cutoff dates per category and country, the instinct is to fit a line and extrapolate. Resist it. The line does not move the way a naive model assumes. A category can jump several months in a single bulletin and then sit frozen for the next two. It can go backward - retrogression - when demand outpaces the annual supply. And the whole system has a seasonal heartbeat: the government fiscal year resets in October, visa numbers refill, and the rhythm of movement early in a fiscal year often looks nothing like the rhythm in August or September when annual limits are running dry.

Here is a concrete version of the problem. Say a category advanced 47 days in the most recent bulletin. Extrapolated blindly, that pace implies a cutoff sweeping through more than a year of priority dates every twelve months. But if you look back three or four years, you might find the same category averaged closer to 18 days a month, with two separate stretches where it went backward. The single most recent number is the least reliable input you have, and it is exactly the one an anxious applicant fixates on.

Why a point estimate is the wrong output

This is the part that changed how I thought about the whole project. For a while I treated "predict the date this person becomes current" as the goal. That framing is quietly dishonest, because it hands back a single day with an implied precision the data cannot support. A system with retrogression, seasonal resets, and demand that shifts by country is not something you forecast to the day. You forecast a distribution.

The useful output is a window with a confidence range attached: given how this category has moved over the past several years, someone at this priority date has historically reached the front in somewhere between roughly this and that, and here is how wide the uncertainty is. A range that admits it might be wrong is more honest than a date that hides it.

There is a discipline that follows from this, and it is easy to skip. If you publish forecasts, you should check them against what actually happened and keep the score. When I later wrote about the finished product, the thing I most wanted to get right was that accountability loop, and it is why the immigration forecast hub I ended up building keeps its confidence ranges and its own historical accuracy visible together rather than printing a clean date and quietly moving on. A model you cannot grade is not a model. It is a guess with good production values.

The honest limits, stated plainly

I want to be direct about what this kind of tooling can and cannot do, because the domain punishes overpromising.

  • A forecast built from public data is a reading of patterns, not a decision from USCIS or the State Department.
  • It cannot see inside anyone's case, it has no access to private government data, and it cannot guarantee an outcome.
  • Immigration timing genuinely changes with agency policy, visa availability, and demand by country and category, and any of those can shift without warning.
  • A category that advanced steadily for a year can stall.

Treat any number the model produces as a planning aid with a wide margin, never a countdown clock. And to be equally plain: none of this is legal advice, and it does not replace an immigration attorney. If a real decision hangs on timing - a job change, a lease, a filing choice - an estimate can inform the conversation, but the decision belongs with someone who knows the full case.

What actually transfers

The specifics here are immigration, but the shape of the problem is not. Anytime you build a forecast on top of a public dataset that was published for reading rather than analysis, the same three things decide whether the result is trustworthy:

  1. How carefully you validate a source that changes shape over time.
  2. Whether you model the seasonality instead of extrapolating the last data point.
  3. Whether you output honest uncertainty instead of false precision.

The Visa Bulletin will keep arriving once a month, a grid of dates that looks more certain than it is. The engineering worth doing is not making it look even more certain. It is turning it into a range someone can plan around, and being willing to check, out loud, how often that range was right.

Comments

No comments yet. Start the discussion.