> This document contains the complete portfolio, including every project case study below. External project links are references; following them is not required to read the full content.

---

[Felipe / Arenillas](https://felipearenillas.dev/)

[Home](https://felipearenillas.dev/#hero) [Projects](https://felipearenillas.dev/#projects) [Experience](https://felipearenillas.dev/#experience) [Contact](https://felipearenillas.dev/#contact) [Download CV](https://felipearenillas.dev/Felipe_Arenillas_CV_EN.pdf)

---

Hello, I'm

# Felipe Arenillas

Backend / Full-Stack Engineer

I design and build backend systems, cloud integrations, and reusable microservice architectures with a focus on maintainability and pragmatic technical decisions.

[View Selected Projects](https://felipearenillas.dev/#projects) [Download CV](https://felipearenillas.dev/Felipe_Arenillas_CV_EN.pdf)

[LinkedIn](https://linkedin.com/in/felipe-arenillas) arenillasfelipewrk@gmail.com Córdoba, Argentina

## About

I hold a degree in Systems Engineering from Universidad Católica de Córdoba. I like to work in an organized and neat way, following best practices and avoiding quick fixes in order to build solid, maintainable solutions. I am proactive and creative, so I usually suggest improvements that add extra value to the project.

I'm also quite sociable and patient, and I get along well with the team and help keep ideas flowing clearly and without friction.

## Selected Projects

Key projects showcasing architecture, backend systems, and reusable microservice design.

Tip: cards marked Open are clickable and include full case-study details.

### Mango

Open

A private app I built for my own finances, bringing my accounts, spending, and net-worth history into one place, with Mercado Pago and Brubank integrations and Veronica, a connected AI assistant.

`React PWA` `NestJS` `PostgreSQL` `Prisma` `Supabase Auth` `Multi-currency` `GPT Actions`

<https://felipearenillas.dev/projects/mango>

### Notifications Microservice

Open

A shared backend service for internal applications to send notifications, keep an inbox history, and deliver live updates to connected users. I proposed, designed, and built the service.

`NestJS` `PostgreSQL` `AWS Lambda` `SQS` `WebSockets` `Reusable Microservice` `System Design`

<https://felipearenillas.dev/projects/notifications-microservice>

### Employee Attendance & Self-Service Platform

Open

An internal platform for Lotería de Córdoba employees, centered on attendance and vacation requests. I designed and built both systems and their integration, from signed QR check-ins to leave approvals, balance rules, and historical recalculation.

`React` `React Native` `NestJS` `PostgreSQL` `QR Attendance` `System Design` `Internal Platform`

<https://felipearenillas.dev/projects/employee-self-service-platform>

### Slots - Casino Machine Inspections

Open

A tablet inspection app I built with one teammate, replacing printed checklists with four sequential review stages and shared machine records. I also mentored my teammate through onboarding and feature development.

`Tablet Workflows` `Sequential Inspections` `Internal Tools` `Mentoring`

<https://felipearenillas.dev/projects/slots>

### Messaging Microservice

Open

A shared backend service I proposed and built for internal applications to offer email-like inboxes and chat conversations, with independent read status and message organization for each participant.

`NestJS` `PostgreSQL` `TypeORM` `Messaging` `Reusable Microservice` `System Design`

<https://felipearenillas.dev/projects/messaging-microservice>

## Experience

Dec 2024 – Present

### Full-Stack Developer (Mid-level)

Lotería de Córdoba · Software Factory

- Part of the Software Factory, the company's internal development team, building products from scratch, delivering them, and maintaining solutions for different business areas.
- Gathering requirements and translating them into technical solutions aligned with business needs, designing architectures and making technical decisions within the defined stack.
- Integrations with cloud services (AWS) and design of asynchronous processes, with continuous improvement of quality, performance and user experience.
- Proposed and owned the end-to-end design and implementation of reusable microservices shared across different projects.
- Collaborate with external software providers to integrate their work with internal systems.
- Co-developed the Slots inspection app in a two-person team and mentored a new teammate through onboarding, code quality, and feature development.

Oct 2024 – Dec 2024

### Full-Stack Developer (Junior)

BircleAI

- Worked on an existing product, adding new features and fixing frontend bugs with Next.js.
- Occasional collaboration on the backend with FastAPI using simple endpoints.

## Stack & Skills

### Backend

`Node.js` `Express.js` `NestJS` `Django`

### Frontend

`React` `TypeScript` `React Native` `Electron` `JavaScript`

### Databases

`PostgreSQL` `MySQL` `SQL` `Sequelize` `TypeORM`

### Cloud / DevOps

`AWS` `Docker` `Terraform` `GitHub Actions` `CI/CD`

### Tools & Architecture

`Git/GitHub` `Jira` `Confluence` `Postman` `UML` `Microservices` `Async Systems Design`

---

Built for my own use · installable web app

## [Mango](https://felipearenillas.dev/projects/mango)

A private app I built for my own finances, bringing my accounts, spending, and net-worth history into one place, with Mercado Pago and Brubank integrations and Veronica, a connected AI assistant.

`React PWA` `NestJS` `PostgreSQL` `Prisma` `Supabase Auth` `Multi-currency` `GPT Actions`

My money was spread across bank accounts and digital wallets. I wanted to know where it was, what I was spending, and how my total net worth had changed over time, without piecing everything together from separate platforms. I couldn't find an existing app that matched my needs and preferences, so I designed and built my own.

A demo with a test account is being developed for this portfolio.

### A Tool Built Around My Own Needs

I built Mango around the way I manage my own money: one place for my accounts, expenses, investments, and financial history, with an AI assistant that can use that information directly. That gives me a complete picture without gathering data from each bank or wallet whenever I have a question.

I am its intended user, and I have no plans to release it to the general public. It has sign-in and a database designed to support multiple users, but the product follows my own requirements. Owning the code means I can change how it works, add an integration when I start using another institution, and adapt the app as my needs evolve.

### One View Across My Accounts

I wanted to follow my finances across all my accounts, wherever the money was held. Mango connects individual transactions to account balances and reports, so I can move from a total to the history behind it.

#### Balances and Net Worth Over Time

See where my money is held, review balances across accounts and currencies, and track my total net worth at different points in time. Currency conversions retain the valuation information used to calculate the result.

#### A Traceable Transaction History

Record and review income, expenses, transfers, debt payments, balance adjustments, and grouped card payments across currencies. Categories, merchants, and tags help me find transactions and understand how I spent my money.

#### Planning and Reminders

Keep upcoming payments, recurring transactions, subscriptions, budgets, and savings goals alongside the same account history. I can postpone, skip, complete, or record due items and receive browser push reminders.

#### Investment Context

Investment records include assets, prices, purchases and sales, dividends, broker cash movements, holdings, valuation, and performance, adding context to the picture of my finances.

### Mercado Pago and Brubank Integrations

Mango integrates with the Mercado Pago digital wallet and the bank Brubank to bring their transactions into my account history. These integrations save me the repetitive work of recording each transaction manually and make keeping the app up to date more practical.

I can also enter transactions directly in the app or ask Veronica, my connected AI assistant, to record them. Each route contributes to the same financial history and reports.

### A Real Use Case: Understanding a Trip's Cost

On a recent trip, I attached the same trip tag to every related transaction. Tags and categories serve different purposes: the category describes the kind of expense, while a tag can connect transactions to a trip or another context. Each transaction can have as many tags as I need, while keeping its category.

After the trip, I filtered by that tag to see the total amount I had spent and break it down by my existing expense categories. The same records supported both views: the cost of the trip as a whole and the kinds of expenses that made up that total.

### Veronica: An Assistant with Financial Context

I wanted an assistant that could access my full financial history without asking me to collect information from different platforms first. Veronica is a GPT connected to Mango that can query my accounts, transactions, net worth, and investment information, then use that context to answer my questions.

#### Record and Maintain Transactions

Veronica can record transactions and modify or delete existing ones. For corrections and deletions, I review and confirm the exact change before it is applied.

#### Explore Patterns and Ask Questions

Veronica can run complex queries, explore spending trends, detect patterns, and offer savings recommendations grounded in my records. I can ask questions about where my money is, how my spending has changed, or what contributes to my net worth.

Veronica accesses the same backend as the app. Its queries and changes use the same financial rules, so a conversation stays connected to the records I see on screen.

### Keeping the Numbers Consistent

Balances are calculated from opening balances and account movements, and reports use that same history. I store amounts as whole numbers in the currency's smallest unit, such as cents, to avoid floating-point rounding errors. Transactions retain their original currency, and converted totals keep the valuation information behind the calculation. Imports, manual edits, and assistant requests all pass through server-side validation.

### What I Built

I designed and implemented the frontend and backend, the account and transaction model, financial calculations, reports, imports, planning flows, and Veronica's integration. The installable React app works on phones and desktop. It connects to a NestJS backend, with PostgreSQL for records, Prisma for database access, and Supabase for sign-in and authorization.

Mango architecture: the phone and desktop web app and Veronica, a connected GPT assistant, use a NestJS API, which reads and writes PostgreSQL through Prisma. Supabase provides sign-in and authorization.

App and Veronica

An installable React + Vite web app and my connected GPT assistant.

The API

NestJS checks identity and access permissions and applies the financial rules.

The records

PostgreSQL + Prisma for accounts, transactions, reports, plans, and investment data.

Veronica connects through GPT Actions and OAuth, which let me authorize its access to Mango's API. The server checks identity, data ownership, and permissions.

---

## [Notifications Microservice](https://felipearenillas.dev/projects/notifications-microservice)

A shared backend service for internal applications to send notifications, keep an inbox history, and deliver live updates to connected users. I proposed, designed, and built the service.

`NestJS` `PostgreSQL` `AWS Lambda` `SQS` `WebSockets` `Reusable Microservice` `System Design`

Company project · Confidential

Developed at Lotería de Córdoba. Source code, screenshots, and recordings cannot be shared due to confidentiality.

### The Problem

At Lotería de Córdoba, several internal applications needed to alert users about new events. Some alerts needed a lasting place in an inbox; others only mattered while the user was connected. I proposed one shared service so each application could request the delivery it needed through a consistent interface.

### My Role

I designed and implemented the backend end to end: the data model, request processing, live delivery, and the integration contract for other applications. I prepared and tested the AWS infrastructure in my personal account and documented the deployment plan. The company's external DevOps team handled production rollout and account-level configuration using that plan.

### How a Notification Reaches a User

The application requesting a notification is the producer. It provides the content, intended recipients, and whether the notification should be stored, delivered live, or both.

1. The producer submits the request directly or places it on a queue for background processing.
2. The service validates the content, source application, and recipients.
3. If storage is requested, it saves the notification and each recipient's state in PostgreSQL for later inbox access.
4. If live delivery is requested, it finds active connections and sends the event to the connected users through WebSocket.
5. For queued requests, failed messages can be isolated through a separate failure queue without failing the whole batch.

If a user is offline, a stored notification remains available when they open their inbox later. A live-only event does not create that inbox history. This distinction lets applications choose the behavior appropriate to each event.

### Architecture

Amazon SQS holds queued requests, and AWS Lambda functions process them. PostgreSQL stores notifications, recipient state, and active connections. API Gateway WebSocket maintains the connections used to push live events, while the NestJS REST API lets applications retrieve stored notifications and inbox data.

Diagram source (Mermaid)

```mermaid
flowchart LR

  subgraph APIs["Producer APIs"]
    direction TB
    APIA[Producer API 1]
    APIB[Producer API 2]
    APIC[Producer API 3]
  end

  subgraph NS["Notifications Microservice"]
    direction LR

    SQS[SQS Queue]
    DLQ[Dead Letter Queue]

    LambdaConsumer["Lambda SQS Consumer"]
    LambdaConnect["Lambda on Connect"]
    LambdaDisconnect["Lambda on Disconnect"]

    DB[(PostgreSQL)]
    REST["REST API (NestJS)"]
    WSG["API Gateway WebSocket"]
  end

  subgraph RA["Frontend Applications"]
    direction TB
    React[React Apps]
  end

  APIA --> SQS
  APIB --> SQS
  APIC --> SQS

  SQS -->|trigger| LambdaConsumer
  LambdaConsumer -->|failed messages| DLQ
  LambdaConsumer <-->|read/write| DB
  LambdaConsumer -->|"real-time notification push"| WSG

  WSG -->|$connect| LambdaConnect
  WSG -->|$disconnect| LambdaDisconnect

  LambdaConnect -->|syncs connection state| DB
  LambdaDisconnect -->|syncs connection state| DB

  REST <-->|read/write| DB

  WSG <-->|$connect / $disconnect| React
  WSG <-->|real-time notification push| React

  React <-->|HTTP requests| REST
```

### Design Decisions and Tradeoffs

#### Direct Requests or Background Processing

Applications can use a direct request-response path or submit queued work. The shared validation contract keeps these entry points consistent while allowing different processing needs.

#### Storage and Live Delivery Are Independent

Saving an inbox item and delivering an immediate event serve different purposes. Keeping them independent supports lasting notifications, temporary live events, and requests that need both.

#### Track Who Is Connected

Connection and disconnection handlers update the active-client records used for live delivery. This gives the send path an explicit record of which connections to target.

### Stack

`NestJS` `PostgreSQL` `AWS Lambda` `Amazon SQS` `API Gateway WebSocket` `REST API` `React clients` `Asynchronous processing` `Reusable microservice design`

---

## [Employee Attendance & Self-Service Platform](https://felipearenillas.dev/projects/employee-self-service-platform)

An internal platform for Lotería de Córdoba employees, centered on attendance and vacation requests. I designed and built both systems and their integration, from signed QR check-ins to leave approvals, balance rules, and historical recalculation.

`React` `React Native` `NestJS` `PostgreSQL` `QR Attendance` `System Design` `Internal Platform`

Company project · Confidential

Developed at Lotería de Córdoba. Source code, screenshots, and recordings cannot be shared due to confidentiality.

### The Platform and My Role

Autogestión is an internal employee platform at Lotería de Córdoba. Employees use it to record attendance and manage HR requests, while managers and HR administrators review requests and maintain the rules that apply to each employee.

I conceived, designed, and implemented the attendance and vacation systems end to end, across the frontend and backend. My work covered secure attendance capture, employee schedules and historical records, vacation eligibility and approvals, and the calculations that keep attendance and leave balances consistent.

### Recording and Interpreting Attendance

Employees record attendance by scanning short-lived, digitally signed QR codes through the authenticated web application. A React Native app generates the codes on registered tablets after operator-approved pairing. Tablets can continue generating codes during connectivity interruptions; employees need a connection to submit their attendance records.

The backend checks the signature, expiry, and device status, and identifies the location from trusted device configuration. Device enrollment uses separate permissions and credentials from everyday operation. Authorized web generators are also supported, with codes signed by the backend.

The system then interprets each record against the employee's expected work. Dated schedule assignments, weekly templates, temporary changes, holidays, and individual exceptions determine the applicable obligation. The rules handle overnight shifts, late arrivals, duplicate scans, corrected departures, missing exits, and work outside the planned schedule.

### Vacation Requests and Approval

Vacation requests were previously handled through email and manual HR checks. HR had to establish how many days an employee was owed and whether the request met the applicable rules. I automated those checks and the approval workflow.

Employees receive an annual allowance based on their length of service. Each allocation period has its own balance and validity dates. HR administrators can extend a period, allowing an older balance to remain available alongside a newer one. The employee selects an eligible period, and the system checks its effective validity and available balance.

The requested dates consume only days the employee was scheduled to work, excluding holidays. A four-day workweek therefore uses that employee's actual schedule. Argentine holidays are imported automatically from the government's official website.

The company organization chart identifies the employee's immediate manager and routes the request for approval or rejection. Administrators can extend allocation periods and edit vacation leave records through their respective permissions.

### Connecting Vacation with Daily Attendance

Approval connects the vacation workflow directly to attendance: the approved dates become justified leave, so an employee taking vacation is not marked absent. The same schedules and holiday calendar determine both the expected attendance and which dates consume vacation balance.

I designed a central fact collector and attendance calculator to give these workflows a consistent interpretation of each day. The collector loads attendance records, schedules, leave justifications, and the employee context applicable to the date. Rules resolve the work obligation and assign each record to the correct work date, including overnight shifts.

The calculator produces daily attendance status, lateness, worked minutes, and scheduled or unscheduled activity, then a dedicated writer stores the result. Reporting and historical recalculation use the same pipeline. Given the same facts, policy, timezone, and evaluation time, it produces the same attendance result.

### Historical Facts and Retroactive Corrections

Correcting a past date requires knowing the employee's circumstances at that time. I implemented historical tracking of facts such as department, length of service, and work schedule, including immutable schedule revisions. Administrators can correct past schedules or add omitted holidays and recalculate the affected employee dates.

One real case involved adding a holiday that had been missed on a past date. Recalculation cleared absence statuses for employees who had correctly stayed home and returned a day of vacation balance to employees who were on vacation. The correction affected both systems because a holiday changes the work obligation and the days chargeable as vacation.

Corrections retain the actor, reason, and operation history. Historical coverage checks block reconstruction when required evidence is missing, keeping the calculation grounded in recorded facts.

### Recoverable Recalculation

Small corrections recalculate attendance within the transaction that changes the facts. Larger changes save durable work and begin background processing after that transaction commits.

Processing uses bounded batches, coordination per employee, leases, retries, and progress tracking. Unfinished operations resume on startup, while periodic checks identify recent dates that need repair or were omitted. This supports corrections that affect many employees without losing the work if processing is interrupted.

### Other Employee Services

I also fully developed the HR news, payslip acknowledgment, and internal messaging modules, including their frontend and backend. HR can target announcements by department or branch, with updates available in the news tab or home-screen notification bell. Employees can review payslips and record their agreement.

Internal messaging (Gmail-like) lets employees compose messages with a subject and body and find colleagues by name or unique employee number (legajo). It includes profile photos, sent messages, favorites, archive, and a trash folder whose messages are deleted after 30 days.

### Messaging and Notification Integrations

I implemented the platform's integrations with two shared backend services that I also developed. They support the internal mailbox and notification delivery; each has its own project description.

Messaging Microservice

Handles conversations and message state for the internal mailbox.

<https://felipearenillas.dev/projects/messaging-microservice>

Notifications Microservice

Delivers the platform's notifications, including in-app alerts.

<https://felipearenillas.dev/projects/notifications-microservice>

### Stack

`React` `PWA` `React Native` `NestJS` `TypeScript` `PostgreSQL` `TypeORM` `ES256 QR signing` `Microsoft Entra ID authentication` `Notifications integration`

---

## [Slots - Casino Machine Inspections](https://felipearenillas.dev/projects/slots)

A tablet inspection app I built with one teammate, replacing printed checklists with four sequential review stages and shared machine records. I also mentored my teammate through onboarding and feature development.

`Tablet Workflows` `Sequential Inspections` `Internal Tools` `Mentoring`

Company project · Confidential

Developed at Lotería de Córdoba. Source code, screenshots, and recordings cannot be shared due to confidentiality.

### From Printed Checklists to Tablet Inspections

Lotería de Córdoba operates casinos across the province of Córdoba, Argentina. Purchased slot machines go through a four-stage component inspection, and the final findings determine the next operational procedure.

Inspectors previously used printed Excel checklists and wrote their findings by hand. Slots brings that process onto a tablet used alongside the physical machine, keeping the findings in a shared digital record.

### Four Sequential Stages

Each stage contains individual checks for machine components, such as the screen and buttons. Inspectors record a green check for an item that is correct, a red cross for a problem, or an intermediate status with a message explaining the finding.

1. Review the machine's individual inspection items on the tablet and record the findings.
2. Complete the stages in order. Each stage must be completed before the next can be completed.
3. After all four stages are complete, close the machine's inspection record.
4. Use the final findings to determine the appropriate next procedure, retaining the record of correct items, problems, and observations.

### An Interface That Follows the Physical Inspection

The interface deliberately requires inspectors to mark each item individually. It prevents marking the whole checklist as correct or incorrect in one action, so recording a result follows the item-by-item review of the physical machine.

Completing an inspection means recording the findings, including problems. Closing the record preserves those results for the next procedure.

### Shared Inspection Records

Inspectors work against the same database. Two people reviewing a particular machine can consult what the other has recorded, keeping the inspection findings available in one shared place.

### My Role and Mentoring

I developed Slots with one teammate at Lotería de Córdoba. He had recently joined the company and was midway through his Systems Engineering degree, so the project also involved substantial mentoring.

Alongside development, I helped him get familiar with the company and guided him on writing clean code, applying good practices, and developing features in an organized way. The work combined delivering an operational application in a two-person team with helping a new colleague build practical development skills.

---

## [Messaging Microservice](https://felipearenillas.dev/projects/messaging-microservice)

A shared backend service I proposed and built for internal applications to offer email-like inboxes and chat conversations, with independent read status and message organization for each participant.

`NestJS` `PostgreSQL` `TypeORM` `Messaging` `Reusable Microservice` `System Design`

At Lotería de Córdoba, different internal applications needed a way for users to exchange messages. I proposed and built one reusable service as the sole engineer, covering the data model, conversation rules, API, and integration design. Each application could then build its own interface on top of the same messaging foundation.

Company project · Confidential

Developed at Lotería de Córdoba. Source code, screenshots, and recordings cannot be shared due to confidentiality.

### One Service for Inboxes and Chat

An internal mailbox needs subjects, sent messages, and folders. A chat needs an ongoing conversation between participants. Both need reliable message storage, read status, and rules for who sees each message. I designed a shared backend that supports both interaction styles, keeping those rules consistent across applications.

### From Sending a Message to Reading It

The application sends message content and recipient information to the service. A conversation, or thread, groups the related messages. The service decides which conversation to use and maintains each participant's view of it.

1. Validate the request and identify the recipients, including the individual recipients represented by a group.
2. Create or reuse a conversation according to the application's messaging mode, then save the message and its recipient records.
3. Track read status separately for each recipient, so one person reading a message does not mark it as read for everyone else.
4. Let each participant organize the conversation independently using favorites, archive, trash, restore, or deletion from their own view.

### Two Conversation Patterns

#### Email-like inboxes

Applications can configure whether a message starts a new conversation or reuses an existing one, supporting messages organized around a subject.

#### Chat conversations

Messages between a pair of participants reuse a stable conversation, keeping their ongoing exchange together.

### Independent State for Each Participant

I separated the shared message content from the records belonging to each recipient. This lets the service deliver the same message to several people while tracking their read status individually.

Conversation organization is also stored per participant. Archiving or removing a conversation from one person's view does not archive or remove it for the other participants. Validation rules keep these state changes consistent.

### Internal Messaging in Autogestión (Gmail-like)

Autogestión is Lotería de Córdoba's internal employee web platform. I fully developed its mailbox and integrated it with this service. Employees compose messages with a subject and body, find colleagues by name or unique employee number (legajo), and manage sent messages, favorites, archive, and trash. In this application, trashed messages are deleted after 30 days.

The employee platform supplies the mailbox interface and colleague selection; the messaging service stores conversations and maintains each participant's message state.

[Explore the Employee Attendance & Self-Service Platform →](https://felipearenillas.dev/projects/employee-self-service-platform)

### Reuse Inside Other Workflows

The same conversation model can support comments attached to a business record. For example, an application for employee objectives could give each objective its own conversation between employee and manager. The application would control who may comment on that objective, while the service would handle the messages and read state.

### Integration with Notification Delivery

Messages and alerts have separate responsibilities. The messaging service stores the conversation; a notification service tells users there is something new to read. I implemented that integration after successful message storage, so a notification outage does not prevent the message from being saved. Read-status updates also attempt to synchronize the related notification without blocking the message flow.

[Notifications Microservice →](https://felipearenillas.dev/projects/notifications-microservice)

### Architecture and Delivery

The service is a NestJS API backed by PostgreSQL, with TypeORM for database access. Message creation and recipient records are saved together in a transaction. Background cleanup removes expired trash in batches, using locks to coordinate work across running instances.

I owned the engineering design, implementation, and integration contracts. An external DevOps partner carried out production deployment and account-level configuration in the company's AWS environment, following my technical blueprint and rollout guidance.

### Stack

`NestJS` `PostgreSQL` `TypeORM` `JWT` `REST API` `Transactional writes` `Background jobs` `Reusable microservice design`

---

## Contact

Córdoba, Argentina

arenillasfelipewrk@gmail.com

[linkedin.com/in/felipe-arenillas](https://linkedin.com/in/felipe-arenillas)

[Download CV](https://felipearenillas.dev/Felipe_Arenillas_CV_EN.pdf) [Text version](https://felipearenillas.dev/portfolio) [Markdown](https://felipearenillas.dev/portfolio.md)

© 2026 Felipe Arenillas
