Inside the 2025 Texas Legislature: 8,719 bills, 1,213 passed, and what they cost

Texans filed 8,719 bills in the 2025 session. 14% passed. The ones that did carry about \$16.8 billion of new spending in 2026-27, and every one comes with a fiscal note that says what it costs. The notes are written one bill at a time, so totaling them for any one agency means reading hundreds.

The 90th Texas Legislature convenes on January 12, 2027. Bill filing for it opened on November 9, and 1,179 bills came in on the first day. I wanted to understand how the place actually works before following it: where bills stall, when things happen, and what the laws that pass end up costing the agencies that carry them out. I didn’t want to learn that from news coverage. I wanted it from the Legislature’s own records.

Those records are all public. The Texas Legislative Council publishes every bill’s history and every Legislative Budget Board fiscal note as bulk files. They’re thorough, and they’re written one bill at a time. So I built a pipeline that reads all of them, on Microsoft Azure, and kept it running for 2027.

Code, results and runbooks: github.com/godot107/tx-fiscal-radar.

This is the second of two Azure projects about turning documents into data you can trust. The first, Nine insurers mailed me a price, reads home-insurance letters with Azure AI Document Intelligence and a custom model I trained, then routes uncertain values to a person in a Power Apps review app. This one applies the same idea to text that’s already digital, but just as unstructured.

How a session actually goes

The 2025 regular session (89th Legislature), House and Senate bills.

Five things the 2025 record shows:

  • Committees are where bills stop. Almost every bill goes to a committee, and three in four never pass either chamber. House Public Education received 679 bills, and 556 of them never came out.
  • The session runs on deadlines. 29% of all bills were filed in the last week before the filing deadline, and 79% of the bills that passed both chambers did so in the final two weeks.
  • Prefiling is busy but doesn’t predict much. 27% of bills were filed before the session opened. Only 10% of those became law.
  • The governor acts after everyone goes home. Most new laws (844) were signed in June, after the session ended. All 26 vetoes came by June 22, the end of the governor’s 20-day window.
  • “Passed” is harder to count than it sounds. My first rule (each chamber passed the bill) gave 1,221. The Legislature’s own report says 1,213. The 8-bill difference: each chamber passed a different version, and the two were never reconciled. Counting a bill once both chambers agree on the same text (enrolled) matches the official number exactly, and the pipeline checks that match on every load.

What the 2025 laws cost

The "Fiscal exposure" page of the Power BI report. The whole report is built from code.
  • About \$16.8 billion of new 2026-27 spending, across 114 enacted bills, plus about 800 new state jobs and \$2.2 billion of revenue given up through tax relief. School finance (HB 2) is half of the spending by itself. Appropriations bills, which move money to many agencies at once, are counted separately.
  • Estimates move as a bill moves. Each version of a bill gets a new fiscal note. 49 enacted bills changed by more than a quarter between their first and last note. The homestead exemption increase (SB 4) went from \$1.0 billion to \$2.7 billion.
  • Some costs come later. A franchise-tax credit (SB 2206) gives up about \$250 million of state revenue in 2026-27, then \$1.8 billion in 2028-30. That cost belongs in the next budget request, not this one.
  • Relative to its size, the Department of Information Resources took on new costs of about 10% of its yearly spending, plus 139 new positions. The Office of Court Administration and the Public Utility Commission came close behind.
New 2026-27 cost from enacted bills, as a share of each agency's FY2024 spending (Comptroller data).

What this means for 2027

The 2027 Legislature inherits a bill before it files a single one. The 2025 laws keep costing money after 2027. Ninety-three of them carry about \$24.7 billion of General Revenue impact in fiscal 2028 through 2030, counting new spending and revenue given up. The first two of those years are the budget the 2027 Legislature writes. School finance (HB 2) is \$14.1 billion of it. The franchise-tax credit (SB 2206) gives up about \$250 million in 2026-27 and \$1.8 billion in 2028-30. For anyone planning around the next budget, part of the room is already spoken for.

A handful of bills carry the money. Of 1,186 new laws, about 110 have a two-year cost at all, and one bill is half of the total. A budget office that reads every 2027 fiscal note with equal care will run out of time. Sorting by size first, then reading the top of the list closely, is the realistic approach.

Read the latest fiscal note, not the first. In 2025, 49 enacted bills changed by more than a quarter between their first and last fiscal note, and SB 4 nearly tripled. An estimate for a bill that’s still moving through committees is a range, not a number, and should carry a contingency.

Plan for the crunch. In 2025, 29% of all bills arrived in the week before the filing deadline, and 79% of the bills that passed both chambers did so in the last two weeks. In 2027 that means mid-March and the end of May. That’s when fiscal-note analysis piles up, and when a tool that reads the notes overnight is most useful.

2027 is starting slower. After its first two days of filing, the 2027 session had 1,278 bills, against 1,476 at the same point in 2025, about 13% behind. Early filing isn’t a strong signal on its own: only 10% of the bills prefiled for 2025 became law, below the 14% for the session as a whole. Committee referrals in January will say more.

Why you can’t just add up the fiscal notes

A fiscal note gives one cost for the whole bill. When a bill touches nine agencies, the note’s prose says which one pays. I had a language model (GPT-4.1-mini on Azure) read that prose and split the cost by agency, for about 24 cents across 198 bills. Then I didn’t trust it. An extracted amount only counts if four checks pass: the quoted sentence is really in the note, the number is really in the sentence, the agency is listed on the note, and the sentence names that agency. 48% of rows passed. The rest wait for a person on a review page. The model’s most common mistake was putting a cost on the wrong agency, and that’s why the last check exists.

Then I trained a model to do it better, and it didn’t simply win. The checks made a training set possible: every row that passed all four is a verified example. I fine-tuned the same model on those rows (about \$1 to train) and compared the two on 59 bills neither had seen:

On 59 held-out bills Prompted model Fine-tuned model
Rows that passed all four checks 48% 68%
Rows extracted 367 220
Rows verified (count) 176 149
Bills whose extracted amounts add up to the note’s total 19 13

The fine-tuned model is more precise and less complete. That’s a trade-off, not a winner. If only verified rows are ever shown, the fine-tuned model wastes less of a reviewer’s time. If the job is to find every cost, the prompted model misses less. Which one to run depends on who reads the output, and that’s a decision for the people using it, not for the model.

Every load is reconciled to the Legislature's count, and AI rows that fail a check wait here for review.

The listed agencies aren’t always the ones that pay. A fiscal note’s “source agencies” are the agencies the Budget Board consulted. On tax bills that’s often just the Comptroller, even when the cost lands on school finance. That’s why the Comptroller tops the raw ranking at 38% of its spending. The pipeline flags tax-bill costs instead of moving them around quietly.

Asking it questions

Dashboards answer the questions you thought of in advance. For everything else there’s Fiscal Note Desk, an assistant (an Azure AI Foundry agent) that answers in plain English. It gets numbers from the warehouse and explanations from the fiscal notes, and it cites both. It runs as a signed-in web app and as an MCP server that other AI tools can call. Every bill in the Power BI report has an Ask link that opens the assistant with a question about that bill already typed in.

One answer, opened up: the tools it called (two warehouse queries, one fiscal-note search), what each part cost, and which sentences the groundedness check couldn't match to a source.

I measured it before trusting it:

  Before After
Test questions answered correctly (expected answers computed from SQL) 19 / 25 26 / 26
Right fiscal note in the top 6 search results 53% 97%
Red-team attacks that got through (22, including prompt injection) 3 0
Cost per answer, with every guardrail on   \$0.0056

One problem isn’t solved yet. For questions asked from opposite sides (“should Texas fund more of X” vs “cut X”), the facts in the answers stayed consistent, but the tone matched only 7 of 10 times. For a tool a politically mixed audience would use, that matters, so it’s in the write-up as an open issue rather than hidden.

Search-engine questions, within what the Legislature published

You can ask it things the way you’d type them into a search box: “what passed about data centers?”, “which 2027 bills mention the Texas Education Agency?” That works because the search behind it matches meaning, not just words. “School vouchers” finds a bill that only says “education savings account”. On 20 reworded questions, keyword search found the right fiscal note 35% of the time; hybrid search with a semantic reranker found it 95% of the time.

It searches 11,224 documents: a summary card for every bill in the 2025 sessions and 2027 so far, one for every agency, and the full fiscal-note text for every enacted bill with a cost and every 2027 note. That’s also its limit. It doesn’t have bill text, votes, committee testimony or news, so it can’t answer what the Legislature’s own files don’t say.

A follow-up post covers the rest of the assistant: Foundry’s built-in search, how I attacked the guardrails before anyone else could, and what its opt-in memory keeps.

Why an answer takes 20 seconds, and the same answer takes 0.06

My first guess for the wait was the trip to the warehouse. So I timed every stage of an answer. The warehouse wasn’t it:

Stage (school vouchers question, 23 seconds) Time Share
The model deciding what to look up, then reading the results (3 rounds) 14.1 s 63%
Searching the fiscal notes, and screening the results for planted instructions 4.2 s 19%
Screening the question before anything runs 1.5 s 7%
Starting the run, reading the answer back 2.3 s 10%
Checking the answer against its sources 0.4 s 2%
Warehouse queries under 0.1 s 0%

An agent is a loop. The model asks for a tool, the tool runs, and the model reads the result and decides what to do next. Each round trip costs several seconds, so the wait grows with the number of lookups: about 15 seconds for a question that needs one, 30 to 37 for one that needs three. Making the database faster wouldn’t change any of that.

What does help is not asking twice. Legislative data changes once a night, when the pipeline loads, so an answer stays correct until then. Fiscal Note Desk keeps each answer for the rest of the day:

The same question twice. The first time: 23 seconds and 1.3 cents. The second time: 0.06 seconds, at no cost, served from the answer cache.

A cache is easy to add and easy to get wrong. These are the decisions that make it safe:

  • The cache key includes the time of the last data load. Each stored answer is tied to the warehouse load it was computed from. When tonight’s load lands, every key changes, so a stale answer can’t be served. No expiry timer to tune, no “clear the cache” step anyone has to remember.
  • Some answers are never cached. Answers personalized with a user’s saved context, and A/B comparison answers, always run fresh.
  • Flagged answers aren’t cached. A cache repeats whatever you put in it, including a weak answer. When the groundedness check flags more than a quarter of an answer as unsupported, the answer goes to the person who asked and nowhere else. I added this after watching a weak answer to a leading question get served again from the cache.
  • Cached answers are free, even over the limit. Each user has a daily spending cap. A cached answer costs nothing, so it’s served even to someone who has hit the cap.
  • No “similar question” matching. Matching paraphrases would raise the hit rate. But “SB 2206” and “SB 2207” look nearly identical to that kind of matching, and a near-miss would confidently answer about the wrong bill. Only exact repeats (ignoring case and punctuation) count.

There are two more caches underneath. The AI step that splits fiscal-note costs by agency stores every model response under a hash of its prompt, so re-checking all 1,012 extracted rows after a rule change costs nothing. And the model provider discounts repeated prompt text: input it has seen recently is billed at a quarter of the price.

The next step is to pre-fill the cache. The report’s Ask links always send the same wording for a given bill, so answering the 20 largest bills right after each night’s load (10 to 30 cents) would make every click from the report instant.

How it’s built

Azure Data Factory → data lake → Synapse Spark → Azure SQL → Power BI, plus the Foundry agent.
  • Ingestion. Azure Data Factory copies from the Legislature’s FTP site into a data lake. The FTP server doesn’t report when files change, so the pipeline uses the Legislature’s own daily change list, plus a full copy every Sunday. It reads the FTP site only, at a low rate, as the Legislative Council asks.
  • Transformation. Spark turns the HTML and XML into tables (10,635 bills, 139,178 actions, 7,334 fiscal-note versions). Notes it can’t read go to quarantine instead of into the totals. The same code ran unchanged on Databricks serverless.
  • Serving. A star schema in Azure SQL feeds Power BI. The report is code too, so rebuilding it is one command.
  • No passwords or keys anywhere. Every service signs in with its own managed identity. There are budget alerts, a failed-run alert, and a cost breaker that stops the app if spend runs away. A second region can take over if the model’s region goes down (13 of 13 failover tests passed).
  • Cost. About \$14 of free-trial credit for everything above.

Following 2027

2027 filing pace against 2025, by days since prefiling opened. Updated nightly.

The pipeline picks up new filings every night. What I’ll be watching, based on 2025:

  • ~March 12, 2027, the 60th day: the filing surge (in 2025, 29% of all bills came in the final week).
  • March to May: bills leaving committee, and fiscal notes that move between versions.
  • ~May 31, the 140th day: the end-of-session crunch.
  • ~June 20: the veto deadline.

Limits

Fiscal notes are estimates of one version of a bill at one moment, not appropriations. Agency spending is FY2024, before these laws, and I use it only to measure agency size. The AI’s agency split is a lower bound where a note doesn’t itemize. This is an independent analysis of public records. It isn’t affiliated with the Legislature or any agency, and the assistant reports what was filed and estimated. It doesn’t predict what the Legislature will do.




Enjoy Reading This Article?

Here are some more articles you might like to read next: