Skip to main content

Welcome to my blog

· One min read
Rayen Dhmaied
DevOps & Site Reliability Engineer at CraftSchoolship

Hi there.

This space is where I share work in more detail. It includes projects I’ve worked on, practical notes, and observations from things I’ve built or learned along the way.

How QuizShip Generates Good Quizzes while Keeping Subscriptions Profitable

· 9 min read
Rayen Dhmaied
DevOps & Site Reliability Engineer at CraftSchoolship

QuizShip turns a topic or a PDF into a quiz, and Claude writes the questions. Each subscription includes a monthly number of AI generations, so every generation is a cost that comes out of the subscription's margin.

The first version cost a median of $0.037 per quiz, but a 40-question quiz took 104 seconds, past the 90-second limit for a generation. The pipeline I run now writes that quiz in about 10 seconds, at about the same cost as before. This post covers how it works, the attempts that got it there, and why it's a fixed pipeline rather than an agent. I used Claude Code to write the evaluation scripts and run the experiments.

Load Testing QuizShip's Game Servers and API with k6

· 24 min read
Rayen Dhmaied
DevOps & Site Reliability Engineer at CraftSchoolship

QuizShip is a live quiz platform. A teacher hosts a game, students join from their phones, and a Go server sends each question to every player over a WebSocket. A Python API handles accounts, billing and the teacher's dashboard. Both run on Kubernetes.

I wanted to know where QuizShip breaks before real traffic showed me, so I copied production into an isolated environment and ran six k6 tests against it. Claude Code helped me design the tests and analyze the data. This post covers what load testing is and how I wrote the tests in k6, including WebSocket tests that hold 30,000 connections. Then it goes through what each test showed, the mistakes I made, and what that load costs on AWS.

Refactoring Terraform into Modules Safely

· 8 min read
Rayen Dhmaied
DevOps & Site Reliability Engineer at CraftSchoolship

At CraftSchoolship, I refactored an older Terraform project that managed our Amazon EKS (managed Kubernetes) stack: the VPC, the cluster and its node groups, storage, and around ten Kubernetes add-ons. All of it lived in one main.tf file of more than a thousand lines.

The code worked, but it was hard to change. Adding one add-on meant scrolling through networking, IAM, EKS, and Helm resources to find the right place.

.
├── main.tf # 1000+ lines: VPC, EKS, add-ons, storage
├── variables.tf
├── outputs.tf
├── providers.tf
├── backend.tf
└── vars.tfvars

I wanted to split it into modules without Terraform recreating the live VPC the EKS cluster was attached to. Terraform's state file records each real resource under its address in the code. Moving a resource into a module changes that address, and Terraform treats a changed address as one resource to destroy and a new one to create.

I moved one module at a time. For each module I copied the resource blocks over, moved their state entries to the new addresses with terraform state mv, and ran terraform plan. Every move ended with a plan showing no changes, meaning Terraform had nothing to create or destroy in AWS. The root main.tf ended up holding only module calls, and the modules now stand up a production-ready EKS cluster in under 15 minutes in each of our three AWS regions.