ashutosh-mathore-profile-picture

Ashutosh Mathore

Full-stack software engineer

Long Beach, CA

Back to selected work

Interconnection Queue Tracker

Making public grid queue reports searchable

I worked across the Next.js and TypeScript interface, Python ingestion jobs, and PostgreSQL data model for the Interconnection Queue Tracker. It brings public reports about proposed power projects into one searchable interface. There are integrations for seven US electricity markets, although available dashboard data depends on which imports have succeeded.

Queue tracker showing market filters, project totals, and grid project data
Interface captured September 4, 2026. Figures reflect the data available at the time.

Working with inconsistent reports

The difficult part was handling differences between the market reports. They used different column names and status values, and some records had missing or duplicate identifiers. I needed to make them searchable together without losing their original market IDs.

I separated the market-specific adapters from the shared normalization code. The adapters translate reports into common project fields, including capacity, fuel, and status.

The normalization code checks several possible capacity-column names and skips values it cannot parse. Projects without an ID are excluded from the project table. Repeated IDs within a market are reduced to one record, keeping the row with the highest capacity. The database uses the market and request ID together as its primary key, so the same identifier can appear in different markets.

Some of these are practical rules rather than guarantees about the source data. For example, an unknown status is currently treated as active. That assumption needs to be understood when interpreting the results.

Keeping imports separate from page requests

A scheduled GitHub Actions workflow runs the Python imports. The Next.js server reads stored data from PostgreSQL instead of fetching every market's report when someone opens the page.

I kept each market's project replacement and summary update in one database transaction. If an import raises an exception, that transaction rolls back and processing continues with the next market. Previously committed data for the failed market remains available. A successful but empty import is a separate case and does not have that protection.

The NYISO downloader also handles reports that are not ready immediately. It retries HTTP 202, 429, and 503 responses with a bounded wait between attempts.

Making the data state visible

If database loading fails or returns no market snapshots, the app attempts to load curated fallback data. That response contains no project rows or live totals, and the interface identifies it as a static fallback.

On the frontend, I implemented market filtering, text search, and pagination, with 50 results per page. The project browser uses a table on desktop and project cards on mobile.

Search and pagination currently happen in the browser after the server loads the project dataset. This keeps filtering local, but the initial payload grows with the number of projects. I would consider server-side filtering and pagination if measurements showed that load time or browser memory had become a problem.

What is tested

The verified CI run passed 30 Python unit tests covering normalization, status handling, duplicate IDs, and snapshot calculations. Web lint and the production build also passed. These checks do not establish end-to-end feed reliability, database rollback behavior, or browser performance.

Verified CI run