A decentralized e-voting platform that stores ballots immutably on the
Ethereum blockchain. Voter codes are hashed with keccak256 before
going on-chain, double-votes are blocked at the contract level, and the whole
thing runs cross-platform from a single Expo codebase.
Votium is a full-stack decentralized voting platform that combines the
transparency of the Ethereum blockchain with the accessibility of a
cross-platform mobile app. Authorized users can create elections, register
candidates and cast votes, every ballot is written immutably on-chain, so
results are publicly auditable and tamper-proof.
Final university grade: 17/20
Architecture
┌─────────────────────────────────────────────┐
│ Mobile App (Expo / RN) │
│ TypeScript · NativeWind · expo-router │
└───────────────────┬─────────────────────────┘
│ HTTPS REST
▼
┌─────────────────────────────────────────────┐
│ Backend (Node.js) │
│ Express · JWT auth · Multer · rate limit │
│ ┌─────────────┴─────────────┐ │
│ ▼ ▼ │
│ MongoDB (Mongoose) Ethereum network │
│ users · candidates ethers.js · HD │
│ off-chain metadata wallet provider │
└───────────────────┬─────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ Solidity Smart Contract (Voto) │
│ keccak256 hashing · mapping-based dedup │
│ VotoRegistado event · immutable ballots │
└─────────────────────────────────────────────┘
How it stays secure
- Cryptographic privacy: voter codes are hashed with
keccak256 before
on-chain storage; a vote can't be linked to an identity without the personal code.
- Double-vote prevention: enforced in the contract via
mapping(address => bool) plus personal-code uniqueness checks.
- Hardened backend: JWT in HttpOnly cookies, brute-force rate limiting,
HTTPS, and on-device SecureStore for tokens.
- Role-based access: separate Admin and User permissions (only admins can see live
vote statistics).
Notable
The backend was prototyped and stress-tested on a Raspberry Pi 3B (ARM Cortex-A53,
1 GB RAM) to validate behaviour under constrained hardware.
Stack
DistributedService
18/20
Distributed systems
A distributed time-series service for IoT fleets: an Erlang session layer
authenticates devices and tracks the cluster with CRDTs, gossip and Raft,
while Java nodes spread events across a DHT with consistent hashing and
answer aggregation queries over gRPC. A Python suite runs performance and
chaos tests against it.
A distributed system for storing and aggregating time-series events from IoT
fleets. A session layer (the SS) written in Erlang fronts the
whole system, events are partitioned across a ring of storage nodes (the
AST) using consistent hashing, and an aggregation server (the
SA) fetches the relevant events and computes results, with a
cache that makes queries near-instant.
Final university grade: 18/20
Architecture
SSSimulator (Dealer)
│ ZMQ
▼
SARouter ──► AggregationService ──► ASTClient
│ ▲ │ gRPC (RxJava + protobuf)
cache engine ▼
(memory) (COUNT/SUM…) FetchEventsHandler
│
ASTService
(DHT routing)
│
EventStorage
(CSV / day)
How it works
- Session front door: every device and consumer authenticates against the SS over a
ZeroMQ ROUTER socket; each connection runs in its own lightweight Erlang process, so thousands of
clients cost almost nothing.
- CRDTs + gossip: the cluster-wide state (who is online, active in the last minute,
per type) lives in LWW-map CRDTs that SS instances merge via periodic gossip, giving eventual
consistency with zero coordination.
- Raft where it matters: consumer registration needs global uniqueness, so those
operations go through a Raft log (leader election, AppendEntries, majority commit) implemented in
raft.erl, a hybrid of strong and eventual consistency by operation type.
- Consistent-hashing ring: a
ConsistentHashRing with virtual nodes
decides which AST node owns each day of data; adding/removing nodes only reshuffles a slice of the
keyspace, and a configurable replication factor keeps data available through node failures.
- gRPC transport: SA and AST communicate over gRPC with RxJava (
rx3grpc)
streaming and protobuf serialization.
- Aggregation engine: supports
COUNT, SUM,
MAX, MIN and SUM_OF_PRODUCTS over filtered event sets, with a
distributed cache coordinated through Cyclon peer sampling.
Components
- SS (Servidor de Sessão), the Erlang entry point: authenticates devices and
consumers, tracks global system state with CRDTs and gossip, runs Raft for operations that need
strong consistency, and pushes real-time notifications over ZeroMQ PUB/SUB.
- SA (Servidor de Agregação), receives aggregation requests, pulls events from the
AST, computes results, and shares a distributed cache with its peers.
- AST (Armazenamento de Séries Temporais), stores events as daily CSV, serves reads
over gRPC, and forms the replicated DHT.
- Test suite: Python scripts for cluster performance, Raft behaviour and chaos
testing, with metrics exported to CSV.
Stack
AirTrail on GKE
17.5/20
Cloud & DevOps
Fully automated deployment and optimization of AirTrail (an
open-source flight-tracking app) on Google Kubernetes Engine. Ansible playbooks
spin the whole cluster up and down, an HPA scales the app under load, and Locust
benchmarks with up to 500 concurrent users measure the difference.
A cloud engineering project built around AirTrail, an open-source
SvelteKit + PostgreSQL app for tracking personal flights. The goal: install it
on Google Cloud with zero manual steps, find its performance bottlenecks under
load, then fix them with autoscaling, and prove the fix with before/after
benchmarks.
Final university grade: 17.5/20
Architecture
┌─────────────────────────────────────────────┐
│ Ansible Playbooks (automation) │
│ gke-cluster-create · airtrail-deploy │
│ airtrail-undeploy · gke-cluster-destroy │
└───────────────────┬─────────────────────────┘
▼
┌─────────────────────────────────────────────┐
│ Google Kubernetes Engine cluster │
│ │
│ LoadBalancer ──► AirTrail pods (SvelteKit) │
│ Service HPA: 2–5 replicas │
│ scale at 60% CPU │
│ │ │
│ ▼ │
│ PostgreSQL pod │
│ │
│ Node autoscaling: up to 5 × e2-medium │
└─────────────────────▲───────────────────────┘
│ 50 / 200 / 500 users
Locust VM on GCP
(login · list flights · save+delete)
Automated install
- One-command deploy: Ansible playbooks (GCP + Kubernetes modules) create the GKE
cluster, deploy PostgreSQL and AirTrail, and tear everything down again, with configuration exposed as
variables.
- LoadBalancer Service: chosen over NodePort to lean on the cloud provider's load
balancing and IP management; the app's
ORIGIN is derived from the assigned IP to avoid
cross-site POST rejections.
- Health-gated steps: each stage waits for the previous one (e.g.
pg_isready before the app starts talking to the database).
Benchmarking & optimization
- Locust load tests: a weighted user scenario (login, listing flights, write-heavy
save/delete) run from a dedicated GCP VM at 50, 200 and 500 concurrent users.
- Baseline findings: a single app instance hit 21% request failures at 200 users and
36% at 500, with steadily climbing latency.
- Fix: a Horizontal Pod Autoscaler (2–5 replicas, scaling at 60% CPU) plus GKE node
autoscaling, with tuned CPU/memory requests and limits.
- Result: at 200 users, failures dropped from 21% to 4% and latency roughly halved;
the minimum of 2 replicas also removed the single point of failure.
- Monitoring: Google Cloud dashboards (per-component CPU, memory, bandwidth) combined
with Locust's live latency/failure charts.
Stack
xicochain
In early development
A passion project, I wanted to learn Rust and build my own blockchain
entirely from scratch. No frameworks, no shortcuts: just me figuring out how
a chain really works underneath the abstractions, one piece at a time.
Early days, and evolving.
xicochain is a passion project. I wanted to learn Rust properly and build my
own blockchain from scratch, no frameworks to hide behind, so the goal is to
assemble every piece of the chain by hand and genuinely understand how blocks,
hashing, consensus and the peer-to-peer layer fit together. It's as much about
the learning as the result.
What it explores
- Blocks & hashing: block structure, linking blocks by cryptographic hash into an
append-only chain.
- Consensus: proof-of-work style validation and chain-selection rules.
- Transactions & state: modelling transactions and the ledger state they mutate.
- Networking: a peer-to-peer layer for propagating blocks and transactions between
nodes.
Why Rust
I picked Rust for xicochain partly to learn it properly,
and partly because a blockchain is a good excuse to:
shared mutable state across a p2p network is exactly where you want the compiler arguing with you.
Stack