Back to projects

On this page

  1. General objective
  2. Technological context
  3. Implemented solution
  4. Complete deletion of reports
  5. Enrichment of reports with Pokémon details
  6. Data flattening
  7. Dataset organization
  8. Randomized report generation
  9. Frontend
  10. Backend
  11. Final CSV output
  12. Relevant links

Poke Queue

System for generating and managing Pokémon reports with asynchronous processing in Azure.

October 6, 2025
FastApiAzureDockerPythonSQLQueueWorkersTerraform

Poke Queue Banner

General objective

This project aimed to extend and modernize a base application by adding new features and demonstrating the ability to adapt and improve an existing system that had to remain deployed and functional in Azure.

Technological context

  • Frontend: Next.js with React
  • Backend: Python API with FastAPI deployed on Azure App Service
  • Asynchronous processing: Azure Functions with Queue Trigger
  • Database: Azure SQL Database
  • Storage: Azure Blob Storage
  • Messaging: Azure Queue Storage
  • External API: PokeAPI
  • Infrastructure as code: Terraform

Implemented solution

The application allows users to generate Pokémon-related reports, manage them in a work queue, and process them asynchronously to produce CSV files with enriched information. The system consists of an interface, a REST API, a database, and serverless functions that respond to queue events.

Complete deletion of reports

To support report deletion, an endpoint was implemented to validate the existence of the requested record and, if present, execute the removal logic. This action not only deletes the database record but also publishes a message to the deletion queue.

The associated worker receives this message and deletes the corresponding file from Azure Blob Storage through the Azure SDK. This ensures a consistent flow between the relational database and the file storage layer.

Enrichment of reports with Pokémon details

The initial API flow was based on querying a Pokémon type to obtain a general list of entities. However, this list did not include detailed information such as base stats or abilities. To address this, the solution combined data from two different endpoints:

  1. Type endpoint:
GET https://pokeapi.co/api/v2/type/{type}
  1. Pokémon detail endpoint:
GET https://pokeapi.co/api/v2/pokemon/{id}

The initial response included values such as the Pokémon name, URL, and slot. Additional requests were then made to fetch information that was useful for report generation, including:

  • Combat stats: HP, attack, defense, speed, and special stats
  • Abilities: names, hidden status, and counts
  • Structured summary for CSV export

Data flattening

A key challenge was the nested structure of the API responses. Statistics and abilities came as dictionaries and arrays, which complicated DataFrame generation and CSV export. The normalization process transformed these structures into a flat and ordered format.

For example, combat stats were converted into direct DataFrame columns:

for stat_item in pokemon_data["stats"]:
    stat_name = stat_item["stat"]["name"]
    base_stat = stat_item["base_stat"]
    flat_data[stat_name] = base_stat

This allowed fields like hp, attack, and speed to be treated as direct columns in the dataset.

Abilities were expanded horizontally to support variability in the number of skills per Pokémon:

abilities = extract_abilities(pokemon_data["abilities"])
for i, ability in enumerate(abilities, 1):
    flat_data[f"ability_{i}_name"] = ability["name"]

Additional summary columns were also created, such as:

all_abilities
total_abilities

This ensured each record was ready for structured export.

Dataset organization

A logical order was defined for the columns in the final report:

  1. Identification fields: name, URL
  2. Main stats
  3. Ability summary
  4. Ability details

This improved readability and simplified downstream analysis in tools like Pandas or Excel.

Randomized report generation

The system also allowed users to define a maximum number of random records to include in each report. This feature was implemented on both the frontend and backend.

Frontend

A form control was used to receive the sample size from the user interface.

Backend

The request endpoint was updated to accept a sampling value. The Pydantic model was extended with a sample_size field, validated as an integer greater than or equal to zero. The corresponding database and stored procedure logic were adjusted to preserve the same functionality with minimal changes.

The worker checks whether the requested sample size is lower than the total available Pokémon for the selected type. If so, it extracts a random subset before generating the final dataset. If the requested value exceeds the available list, the entire list is returned.

Final CSV output

The generated CSV was structured as follows:

name,url,hp,attack,defense,special-attack,special-defense,speed,total_abilities,all_abilities,ability_1_name,ability_2_name,ability_3_name
charmander,https://pokeapi.co/api/v2/pokemon/4/,39,52,43,60,50,65,2,"blaze, solar-power",blaze,solar-power,
charmeleon,https://pokeapi.co/api/v2/pokemon/5/,58,64,58,80,65,80,2,"blaze, solar-power",blaze,solar-power,
charizard,https://pokeapi.co/api/v2/pokemon/6/,78,84,78,109,85,100,2,"blaze, solar-power",blaze,solar-power,

Relevant links

  • Portal UI deployed
  • API deployed
  • API repository
  • UI repository
  • Azure Function repository
  • Database repository
  • Architecture repository
  • Demonstration of main features
Back to projects