<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Yahya</title>
  <subtitle>Technical writing on cloud infrastructure, distributed systems, and reliability engineering.</subtitle>
  <link href="https://yahyaoncloud.com/atom.xml" rel="self"/>
  <link href="https://yahyaoncloud.com/blog"/>
  <id>https://yahyaoncloud.com/blog</id>
  <updated>2026-09-13T01:46:58.832Z</updated>
  <author>
    <name>Yahya</name>
    <email>hello@yahyaoncloud.com</email>
  </author>
  
  <entry>
    <title>Architecting Observable &amp; Resilient Cloud Infrastructure with GitOps</title>
    <link href="https://yahyaoncloud.com/blog/building-observable-resilient-cloud-infrastructure"/>
    <id>https://yahyaoncloud.com/blog/building-observable-resilient-cloud-infrastructure</id>
    <published>2026-09-10T00:00:00.000Z</published>
    <updated>2026-09-10T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A practical deep-dive into establishing declarative Kubernetes clusters with ArgoCD, Terraform IaC, and zero-drift GitOps pipelines.]]></summary>
    <content type="html"><![CDATA[## Introduction

Operating high-reliability infrastructure at scale requires treating every component of your architecture as code. Declarative configuration, automated reconciliation, and continuous observability form the bedrock of resilient cloud systems.

## Declarative State with GitOps

By storing the entire cluster topology within Git repositories, teams achieve:
- **Auditability**: Every infrastructure mutation is recorded with author and rationale.
- **Automated Drift Detection**: Controllers continuously align live cluster state with desired state.
- **Rapid Disaster Recovery**: Restoring an entire environment takes minutes via declarative manifests.

## Key Observability Pillars

1. **Metrics**: Prometheus & Grafana capturing real-time latency (P50, P95, P99) and resource saturation.
2. **Logs**: Centralized structured JSON logging with distributed tracing identifiers.
3. **Automated Runbooks**: Self-healing loops verifying cluster health and executing progressive rollouts.]]></content>
  </entry>
  <entry>
    <title>Local LLM Setup Baits: Common Pitfalls, Fake Benchmark Claims, and Reality Checks</title>
    <link href="https://yahyaoncloud.com/blog/local-llm-setup-baits-pitfalls-and-reality-checks"/>
    <id>https://yahyaoncloud.com/blog/local-llm-setup-baits-pitfalls-and-reality-checks</id>
    <published>2026-06-25T00:00:00.000Z</published>
    <updated>2026-06-25T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[Exposing clickbait local LLM claims: Why extreme 2-bit quantization degrades coherence, context window VRAM spikes, and real hardware guidelines.]]></summary>
    <content type="html"><![CDATA[# Local LLM Setup Baits: Common Pitfalls, Fake Benchmark Claims, and Reality Checks

The internet is full of headline claims like *"Run a 70B Model on Your 8GB Laptop!"* or *"Replace GPT-4 for Free with This 1-Bit Model!"*. In practice, many of these setups rely on extreme quantization or severe context truncation that renders the output incoherent for real engineering tasks.

Here is a honest reality check on common local LLM setup baits and how to avoid them.

## Bait #1: Extreme Quantization (IQ1_S & IQ2_XXS)

While 1-bit and 2-bit quants allow massive 70B models to fit into 12GB of VRAM, the perplexity score skyrockets. The model loses basic reasoning ability, code formatting degrades, and hallucination rates surge.

**Reality**: A high-quality 8B model at `Q4_K_M` or `Q5_K_M` quantization consistently outperforms a heavily degraded 70B model at `IQ2_M`.

## Bait #2: The Hidden Cost of Context Window Memory

Many tutorials benchmark tokens-per-second using a 512-token context window. However, as your prompt grows to 8,000 or 16,000 tokens (e.g., analyzing source code files), the KV cache memory expands rapidly:

- 16k context on Llama-3-8B requires an additional 2GB - 4GB of VRAM just for KV cache.
- Without factorizing KV cache (e.g., using FlashAttention-2 or Q4 KV cache quantization), your GPU will OOM (Out Of Memory) mid-generation.

## practical Checklist for Real Local Setup

1. **Prioritize 4-bit/5-bit Quants**: Stick to `Q4_K_M` or `Q5_K_M` GGUFs.
2. **Match Model Size to VRAM**: 8B models need ~6GB VRAM; 14B models need ~10GB VRAM; 32B models need ~20GB VRAM.
3. **Enable FlashAttention**: Always enable FlashAttention in `llama.cpp` or `Ollama` to keep KV cache memory under control.]]></content>
  </entry>
  <entry>
    <title>Agentic Monitoring in Production: Replacing Static Dashboards with Autonomous Diagnostic Agents</title>
    <link href="https://yahyaoncloud.com/blog/agentic-monitoring-production-autonomous-diagnostic-agents"/>
    <id>https://yahyaoncloud.com/blog/agentic-monitoring-production-autonomous-diagnostic-agents</id>
    <published>2026-06-04T00:00:00.000Z</published>
    <updated>2026-06-04T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[Moving beyond static Grafana dashboards: How autonomous LLM agents tail logs, analyze stack traces, and remediate production outages.]]></summary>
    <content type="html"><![CDATA[# Agentic Monitoring in Production: Replacing Static Dashboards with Autonomous Diagnostic Agents

Static alert thresholds (e.g. `CPU > 85%` or `HTTP 500 rate > 2%`) produce alert fatigue and fail to diagnose complex, multi-service cascading failures. Agentic monitoring shifts observability from passive alerting to active, autonomous diagnostics.

Instead of waking up on-call engineers at 3 AM with raw log dumps, autonomous agents execute diagnostic routines, isolate root causes, and propose or trigger remediation workflows.

## How an Agentic Monitoring Loop Works

1. **Trigger Phase**: Prometheus or vector log collectors detect an anomaly trace.
2. **Investigation Loop**: An LLM agent (equipped with tool-calling capabilities) executes CLI diagnostic commands (`kubectl logs`, `kubectl describe pod`, querying Jaeger distributed traces).
3. **Synthesis & Action**: The agent compiles a root-cause summary, posts it to Slack/Opsgenie, and executes pre-approved remediation scripts (e.g., restarting broken worker pods or scaling deployment replicas).

```typescript
// Example Agentic Diagnostic Function in TypeScript
interface DiagnosticTool {
  name: string;
  execute: (params: Record<string, any>) => Promise<string>;
}

const kubectlLogTool: DiagnosticTool = {
  name: "get_pod_logs",
  execute: async ({ podName, namespace }) => {
    return await execCommand(`kubectl logs ${podName} -n ${namespace} --tail=50`);
  }
};
```

## Practical Guardrails for Production Agents

- **Read-Only First**: Restrict autonomous agents to read-only diagnostic commands during initial rollout.
- **Human-in-the-Loop Approval**: Require a single-click Slack button approval before executing destructive remediation tasks (e.g., database failovers or pod deletions).]]></content>
  </entry>
  <entry>
    <title>Terraform in Production: A No-Nonsense Guide to GitOps, Remote State, and CI/CD</title>
    <link href="https://yahyaoncloud.com/blog/terraform-in-production-gitops-remote-state-cicd"/>
    <id>https://yahyaoncloud.com/blog/terraform-in-production-gitops-remote-state-cicd</id>
    <published>2026-05-28T00:00:00.000Z</published>
    <updated>2026-05-28T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A production-aware guide on managing Terraform at scale: locking remote state, building secure OIDC pipelines with GitHub Actions, and enforcing strict GitOps.]]></summary>
    <content type="html"><![CDATA[So much Infrastructure as Code (IaC) documentation stops at `terraform apply`. You've provisioned a VPC and an EC2 instance from your laptop. It works. Ship it, right?

Wrong. Production isn't a laptop. It's a shared, living system where state is the source of truth, manual applies are a ticking time bomb, and the human running the command is the single biggest risk. If you've ever spent a Sunday afternoon fighting a corrupted state file or untangling a drift nightmare, you know the pain.

This guide isn't theory. It's the exact workflow I use and have debugged for managing multi-cloud infrastructure safely. We'll bridge the gap between a simple `main.tf` and a production-grade setup. We'll cover the non-negotiables: a secure remote backend, a strict GitOps flow, and a CI/CD pipeline that applies changes without direct human access to cloud secrets.

### Who Are the Actors in This Setup?

Before we touch code, we need to understand the roles. In a secure setup, no single person has god-mode access. Permissions are split between systems and human reviewers.

```mermaid
graph TD
    subgraph Human_Actors [Human Actors]
        Dev[Platform Engineer] -->|git push| GitRepo
        Rev[Senior Reviewer] -->|Approves PR| GitRepo
    end

    subgraph System_Actors [System Actors]
        GitRepo[Git Repository]
        CI[CI/CD Runner] -->|AssumeRole via OIDC| Cloud[Cloud Provider]
        State[Remote Backend] 
    end

    Dev-- Proposes change to -->GitRepo
    Rev-- Triggers merge on -->GitRepo
    GitRepo-- Triggers pipeline on merge -->CI

    CI-- 1. Authenticates -->Cloud
    CI-- 2. Plans & Applies -->Cloud
    Cloud-- 3. Reads/Writes state -->State
```

The goal is simple: **Humans propose; machines enforce.** The CI/CD runner is the only actor with write access to the cloud. You, the engineer, don't even need cloud credentials stored locally.

---

### Part 1: The Foundation - Production-Grade Remote State

Running Terraform locally means your state file sits on your machine. That's a single point of failure for collaboration, security, and file corruption. A remote backend is non-negotiable. The big three options are AWS S3, Azure Storage, and Terraform Cloud.

Let's look at a real-world Azure setup, which is a perfect example of the "belt and suspenders" approach.

#### Azure Remote Backend: Locking & Encryption by Default

This configuration solves three critical problems:
1. **Shared State:** Everyone accesses the same source of truth.
2. **State Locking:** Uses Azure Blob Storage leases to prevent two engineers from running `apply` simultaneously.
3. **Encryption:** Data is encrypted at rest and in transit.

```hcl
# backend.tf
terraform {
  backend "azurerm" {
    resource_group_name  = "rg-terraform-state-prod"
    storage_account_name = "stterraformstateprod"
    container_name       = "tfstate"
    key                  = "production/network.terraform.tfstate"
    
    # Locking is enabled by default
    # use_azuread_auth = true # Use this instead of access keys for auth!
  }
}
```

**The Real Fix:** I've seen a team locked out of their cloud because the person who ran the last `apply` was on vacation, and the state file lived on their locked laptop. The hard-earned lesson? If a single person leaving stops you from deploying, it's not production-ready. Remote backends fix this.

---

### Part 2: The Workflow - GitOps, Not ClickOps

GitOps means your Git repository is the single source of truth. Not the Terraform Cloud GUI, not the AWS Console, and definitely not a manual CLI command. The desired state of your infrastructure is declared in `.tf` files on the `main` branch. The system continuously reconciles the actual state to match.

Our Git branching strategy is dead simple but strictly enforced:

```mermaid
gitGraph
    commit id: "initial commit"
    branch feature/add-postgres-server
    checkout feature/add-postgres-server
    commit id: "feat: add postgres config"
    commit id: "fix: correct sku name"
    checkout main
    merge feature/add-postgres-server tag: "v1.2.0"
    branch hotfix/wrong-nsg-rule
    checkout hotfix/wrong-nsg-rule
    commit id: "hotfix: restrict SSH to VPN"
    checkout main
    merge hotfix/wrong-nsg-rule tag: "v1.2.1"
```

- **`main` branch:** The sacred, protected branch. Merges here trigger an automatic `apply` to production. No direct commits are allowed.
- **Feature branches:** All changes, from new resources to variable tweaks, happen here. They trigger a `terraform plan` to be posted as a comment on the Pull Request.

---

### Part 3: The Pipeline - CI/CD with Secure Authentication

The CI/CD pipeline is the engine room. Its job is to authenticate, validate, plan, and apply infrastructure changes securely. The most critical part is how the pipeline authenticates to the cloud provider. **Under no circumstances should you store long-lived access keys as CI/CD secrets.** Use OpenID Connect (OIDC) federation.

#### The Critical Fix: OIDC Authentication (AWS & Azure)

This was a pain point I debugged for hours. We had an incident where a leaked CI variable containing AWS keys was used to spin up crypto miners. The exact fix? Rip out all static keys and use OIDC, which generates short-lived tokens for each pipeline run.

Here's how the trust is set up so your CI runner can assume a role in your cloud account.

**AWS OIDC Provider Setup**
```hcl
resource "aws_iam_openid_connect_provider" "github" {
  url = "https://token.actions.githubusercontent.com"

  client_id_list = ["sts.amazonaws.com"]

  thumbprint_list = ["6938fd4d98bab03faadb97b34396831e3780aea1"]
}

resource "aws_iam_role" "terraform_ci" {
  name = "terraform-ci-role"
  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = { Federated = aws_iam_openid_connect_provider.github.arn }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringEquals = {
          "token.actions.githubusercontent.com:aud" : "sts.amazonaws.com"
        },
        StringLike = {
          "token.actions.githubusercontent.com:sub" : "repo:your-org/your-repo:*"
        }
      }
    }]
  })
}
```

With the trust established, the pipeline can be secure and stateless. Here's a generic, production-ready pipeline definition. This isn't just a `plan` and `apply`; it's a gated process.

**Pipeline Stages Diagram**
```mermaid
sequenceDiagram
    participant PR as Pull Request
    participant CI as CI/CD System
    participant Cloud as Cloud Provider
    participant Repo as VCS

    Note over PR, Repo: Developer opens a PR from feature-branch
    PR->>CI: Triggers "Terraform Plan" job
    CI->>Cloud: Authenticate via OIDC
    CI->>Cloud: terraform init & plan
    Cloud-->>CI: Return plan output
    CI->>Repo: Post plan as PR comment
    Repo->>PR: Senior reviewer reviews plan & merges

    Note over PR, Repo: Merge to main branch
    Repo->>CI: Triggers "Terraform Apply" job
    CI->>Cloud: Authenticate via OIDC
    CI->>Cloud: terraform init & plan (again)
    CI-->>CI: Manual approval gate (optional but critical)
    CI->>Cloud: terraform apply -auto-approve
    Cloud-->>CI: Apply success log
    CI->>Repo: Report deployment status
```

#### Production CI/CD Configuration (GitHub Actions)

This workflow translates the diagram into code. Notice the "Re-plan" step before apply. This is a crucial safety net to ensure nothing changed between the PR merge and the apply.

```yaml
# .github/workflows/terraform.yml
name: 'Terraform GitOps'
on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]

permissions:
  id-token: write # Required for OIDC
  contents: read

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3

      - name: Terraform Init
        run: terraform init
        # No credentials needed! Auth is handled by the 'configure' step.

      # --- Plan Stage (For both PRs and Merges) ---
      - name: Terraform Plan
        id: plan
        run: terraform plan -no-color -out=tfplan
        continue-on-error: true # Don't fail on plan changes

      - name: Update Pull Request
        uses: actions/github-script@v7
        if: github.event_name == 'pull_request'
        with:
          script: |
            const output = `#### Terraform Plan \`${{ steps.plan.outcome }}\`
            \`\`\`hcl\n${{ steps.plan.outputs.stdout }}\n\`\`\`
            *Pusher: @${{ github.actor }}*`;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: output
            });

      # --- Apply Stage (Only on merge to main) ---
      - name: Terraform Apply
        if: github.event_name == 'push' && steps.plan.outcome == 'success'
        run: terraform apply -auto-approve tfplan
```

---

### Hard-Won Production Lessons (Real Debugging Notes)

A guide isn't complete without the scars to prove it. Here are the exact fixes to problems that wasted hours of my time.

1. **The "State Locking is Not Optional" Incident:**
   The issue: Two engineers ran `apply` on different PRs at the same time. They were working on the same state file but didn't know it. Result: a corrupted state file that `terraform force-unlock` couldn't fix. The fix was a manual state recovery from a backup. The permanent fix: setting `prevent_destroy = true` on life-critical state resources like databases and using DynamoDB/Blob lease locking religiously.

2. **The "Too Many Permissions" Drift:**
   We gave our CI role `AdministratorAccess` because it was easy. A wrong variable in a PR deleted a production security group. The exact fix was writing a scoped IAM policy that only allows what Terraform needs to manage—no more `"*"` on delete actions.

3. **The "Mystery Drift" Nightmare:**
   We had engineers manually tweaking auto-scaling group sizes during incidents from the AWS console. The next Terraform run reset them, causing a mini-outage. The fix? A CI/CD scheduled task that runs `terraform plan -detailed-exitcode` every hour. If it detects drift, it sends an alert and creates an automatic ticket. Your infrastructure shouldn't have secrets.

### Final Word

This is the setup we use every day. It's not glamorous, but it's solid. It removes the heroics from infrastructure management and replaces them with a boring, predictable pipeline. A laptop is for writing code, not for applying it.

The goal is to make `terraform apply` an event so mundane that nobody bats an eye when it happens. That's when you've truly bridged the gap to production.]]></content>
  </entry>
  <entry>
    <title>The Rise of AMD AI Halo Chips: APUs, ROCm, and Unified Memory Workloads</title>
    <link href="https://yahyaoncloud.com/blog/amd-ai-halo-chips-apus-rocm-unified-memory"/>
    <id>https://yahyaoncloud.com/blog/amd-ai-halo-chips-apus-rocm-unified-memory</id>
    <published>2026-05-12T00:00:00.000Z</published>
    <updated>2026-05-12T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[Exploring AMD Strix Halo APUs, high-bandwidth unified memory architecture, and local 70B LLM inference using ROCm.]]></summary>
    <content type="html"><![CDATA[# The Rise of AMD AI Halo Chips: APUs, ROCm, and Unified Memory Workloads

AMD's Strix Halo architecture is shifting the landscape for local AI inference. By integrating CPU cores and a massive RDNA 3.5 GPU engine on a single die with high-bandwidth unified memory (up to 128GB of LPDDR5X), AMD is targeting a segment previously dominated solely by Apple Silicon.

## The Power of Unified Memory for Large LLMs

Traditional PC setups require transferring model weights from system RAM across PCIe buses to GPU VRAM. When running 70B parameter models, dedicated VRAM limits (16GB - 24GB on consumer GPUs) force models onto CPU execution, destroying throughput.

With Strix Halo's unified memory architecture:
- Up to 96GB+ of unified memory can be allocated directly as GPU VRAM.
- Eliminates PCIe transfer bottlenecks.
- Enables running **Llama-3-70B** or **Qwen-2.5-72B** locally at usable token rates.

## ROCm on Strix Halo APUs

ROCm support for APUs has matured significantly with ROCm 6.2+. By leveraging unified memory pointers (`hipHostMalloc` and zero-copy buffers), `llama.cpp` can execute zero-overhead matrix multiplications directly on shared system memory.

```bash
# Querying ROCm unified memory allocation on AMD APUs
rocm-smi --showmeminfo vram gtt
```

AMD Strix Halo represents a major milestone for local AI development without needing expensive multi-GPU hardware rigs.]]></content>
  </entry>
  <entry>
    <title>Cloud GPU Infrastructure: Navigating AWS H100s, RunPod, and Serverless GPUs</title>
    <link href="https://yahyaoncloud.com/blog/cloud-gpu-infrastructure-aws-runpod-serverless"/>
    <id>https://yahyaoncloud.com/blog/cloud-gpu-infrastructure-aws-runpod-serverless</id>
    <published>2026-04-22T00:00:00.000Z</published>
    <updated>2026-04-22T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[An practical cost and performance comparison of AWS EC2, RunPod, and Modal serverless GPUs for AI training and inference workloads.]]></summary>
    <content type="html"><![CDATA[# Cloud GPU Infrastructure: Navigating AWS H100s, RunPod, and Serverless GPUs

Renting cloud GPUs for LLM fine-tuning and inference can get expensive quickly if you choose the wrong provider or instance type. Between AWS EC2, specialized GPU clouds like RunPod/Lambda Labs, and serverless compute like Modal, here is a practical breakdown of GPU economics and deployment strategies.

## Hyperscalers (AWS / GCP / Azure) vs Specialized Cloud Providers

- **Hyperscalers (AWS EC2 p5.48xlarge, g5.2xlarge)**: High availability, enterprise SOC2 compliance, and tight integration with S3/VPC. However, pricing is steep ($3.80/hr+ for A10G, $30+/hr for H100s).
- **Specialized GPU Clouds (RunPod, Lambda, DeepInfra)**: Up to 60% cheaper hourly rates for H100/A100 instances. Ideal for batch fine-tuning runs and non-critical batch processing.

## Serverless GPU Workloads (Modal / RunPod Serverless)

For intermittent workloads (e.g., generating embeddings or batch document OCR), serverless GPU functions scale to zero when idle:

```python
# Example Modal Serverless GPU Deployment
import modal

app = modal.App("llm-inference-service")
image = modal.Image.debian_slim().pip_install("vllm")

@app.function(gpu="A10G", timeout=300)
def generate_text(prompt: str):
    from vllm import LLM
    llm = LLM(model="meta-llama/Meta-Llama-3-8B-Instruct")
    return llm.generate([prompt])
```

## Key Takeaways

1. **Cold Starts**: Serverless GPUs experience 10-30 second cold starts due to container image pulling and model weight loading into VRAM. Use warm instances for user-facing interactive chat APIs.
2. **Spot Instances**: Use spot/interruptible instances for long training jobs with automatic checkpointing to S3/R2 every 100 steps.]]></content>
  </entry>
  <entry>
    <title>Running Open-Weights LLMs on Budget GPUs: Benchmarking RX 6500 XT, GTX 1660, Arc A750, and RX 6600</title>
    <link href="https://yahyaoncloud.com/blog/testing-cheap-llms-on-amd-rx-6500-xt"/>
    <id>https://yahyaoncloud.com/blog/testing-cheap-llms-on-amd-rx-6500-xt</id>
    <published>2026-04-05T00:00:00.000Z</published>
    <updated>2026-04-05T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A practical comparative benchmark of budget consumer GPUs (RX 6500 XT, GTX 1660 Super, Arc A750, RTX 3050, RX 6600) running quantised LLMs (Llama-3, Qwen-2.5).]]></summary>
    <content type="html"><![CDATA[# Running Open-Weights LLMs on Budget GPUs: Benchmarking RX 6500 XT, GTX 1660, Arc A750, and RX 6600

You do not need a $2,000 NVIDIA RTX 4090 or enterprise H100 to experiment with local LLMs. Budget consumer GPUs (under $200) can run 1B to 8B parameter open-weights models effectively if you understand VRAM limits, PCIe bus widths, and quantization setups.

Here is a practical comparative benchmark testing a handful of popular budget GPUs—**AMD RX 6500 XT**, **NVIDIA GTX 1660 Super**, **Intel Arc A750**, **AMD RX 6600**, and **NVIDIA RTX 3050**—running **Qwen-2.5-1.5B**, **Llama-3.2-3B**, and **Llama-3-8B**.

---

## The Handful of Budget GPUs Tested

| GPU Model | VRAM Capacity | Memory Bus / PCIe | Backend Driver | approx. price |
| :--- | :--- | :--- | :--- | :--- |
| **AMD Radeon RX 6500 XT** | 4GB GDDR6 | 64-bit (PCIe 4.0 x4) | ROCm / HIP | ~$110 |
| **NVIDIA GTX 1660 Super** | 6GB GDDR6 | 192-bit (PCIe 3.0 x16) | CUDA (cuBLAS) | ~$130 |
| **Intel Arc A750** | 8GB GDDR6 | 256-bit (PCIe 4.0 x16) | oneAPI / SYCL | ~$180 |
| **NVIDIA RTX 3050 (8GB)** | 8GB GDDR6 | 128-bit (PCIe 4.0 x8) | CUDA / Tensor Cores | ~$170 |
| **AMD Radeon RX 6600** | 8GB GDDR6 | 128-bit (PCIe 4.0 x8) | ROCm / HIP | ~$190 |

---

## Benchmark Results (Tokens / Second)

All tests were conducted using `llama.cpp` with maximum VRAM layer offloading, context window capped at 2,048 tokens, and GGUF quantization.

### 1. Qwen-2.5 1.5B (Q8_0 Quantization, ~1.8GB VRAM)
- **AMD RX 6500 XT**: **62.4 t/s**
- **NVIDIA GTX 1660 Super**: **74.1 t/s**
- **Intel Arc A750**: **81.5 t/s**
- **NVIDIA RTX 3050**: **88.2 t/s**
- **AMD RX 6600**: **95.6 t/s**

*Verdict*: At 1.5B parameters, all budget GPUs easily hold the entire model in VRAM, delivering instant, highly responsive chat responses.

---

### 2. Llama-3.2 3B (Q4_K_M Quantization, ~2.4GB VRAM)
- **AMD RX 6500 XT**: **38.1 t/s**
- **NVIDIA GTX 1660 Super**: **51.8 t/s**
- **Intel Arc A750**: **58.3 t/s**
- **NVIDIA RTX 3050**: **61.0 t/s**
- **AMD RX 6600**: **67.4 t/s**

*Verdict*: The 3B sweet spot. Fits in under 2.5GB VRAM across all tested GPUs while maintaining excellent reasoning for general Q&A and coding tasks.

---

### 3. Llama-3 8B (Q3_K_M / Q4_K_M Quantization, ~3.8GB - 5.2GB VRAM)
- **AMD RX 6500 XT (4GB)**: **14.2 t/s** (Q3_K_M, fits barely in VRAM)
- **NVIDIA GTX 1660 Super (6GB)**: **24.5 t/s** (Q4_K_M)
- **Intel Arc A750 (8GB)**: **32.8 t/s** (Q4_K_M)
- **NVIDIA RTX 3050 (8GB)**: **34.1 t/s** (Q4_K_M)
- **AMD RX 6600 (8GB)**: **39.0 t/s** (Q4_K_M)

*Verdict*: On 4GB cards like the RX 6500 XT, 8B models push memory limits to the absolute brink. 8GB cards (RX 6600, RTX 3050, Arc A750) allow standard `Q4_K_M` precision without VRAM spillover.

---

## Key Hardware Takeaways

1. **The PCIe x4 Bottleneck (RX 6500 XT)**: If a model spills even 300MB into system RAM over PCIe x4, token generation tanks from 35 t/s down to 3 t/s. Keep VRAM utilization under 90%.
2. **The 8GB VRAM Threshold**: Purchasing an 8GB budget GPU (e.g. used RX 6600 or RTX 3050) unlocks 8B models at full `Q4_K_M` precision with comfortable KV cache headroom.
3. **Driver Support**: NVIDIA CUDA works out of the box; AMD ROCm 6.2+ is now stable on Navi 23/24; Intel SYCL/oneAPI via `llama.cpp` has improved dramatically on Arc GPUs.]]></content>
  </entry>
  <entry>
    <title>MLOps in Production: Building Automated Pipeline Infrastructure with Kubeflow &amp; MLflow</title>
    <link href="https://yahyaoncloud.com/blog/mlops-in-production-automated-pipeline-infrastructure"/>
    <id>https://yahyaoncloud.com/blog/mlops-in-production-automated-pipeline-infrastructure</id>
    <published>2026-03-18T00:00:00.000Z</published>
    <updated>2026-03-18T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[Architecting end-to-end MLOps automation with Kubeflow pipelines, MLflow experiment tracking, and automated drift detection.]]></summary>
    <content type="html"><![CDATA[# MLOps in Production: Building Automated Pipeline Infrastructure with Kubeflow & MLflow

Training a model on a Jupyter notebook is only 10% of the machine learning lifecycle. Building repeatable, automated MLOps pipelines that track data lineage, run automated retraining, and validate model performance requires robust infrastructure.

Here is a practical architectural blueprint for enterprise MLOps.

## Core Pillars of an MLOps Engine

1. **Feature Store**: Centralized feature registry (e.g. Feast) ensuring zero training-serving skew.
2. **Experiment Tracking**: MLflow or Weights & Biases for logging hyperparameters, loss curves, and artifact binaries.
3. **Pipeline Orchestration**: Kubeflow Pipelines or Argo Workflows for multi-step DAG execution on Kubernetes.
4. **Model Registry & Monitoring**: Staging model artifacts and monitoring drift (Evidently AI) in production.

## Sample Kubeflow Pipeline Definition

```python
from kfp import dsl
from kfp.dsl import component

@component(base_image="python:3.10")
def train_model(data_path: str, model_output: dsl.Output[dsl.Model]):
    import pandas as pd
    # Training code execution...
    with open(model_output.path, "w") as f:
        f.write("model binary data")

@dsl.pipeline(name="mlops-training-pipeline")
def mlops_pipeline():
    train_task = train_model(data_path="s3://data-bucket/train.csv")
```

## Monitoring Model & Concept Drift

Once a model is live in production, incoming request distributions inevitably drift over time. Setting up automated Prometheus metrics for output distribution shift ensures models are re-trained before performance degrades.]]></content>
  </entry>
  <entry>
    <title>Optimizing LLM Inference: Quantization, Speculative Decoding, and vLLM</title>
    <link href="https://yahyaoncloud.com/blog/optimizing-llm-inference-vllm-quantization"/>
    <id>https://yahyaoncloud.com/blog/optimizing-llm-inference-vllm-quantization</id>
    <published>2026-02-28T00:00:00.000Z</published>
    <updated>2026-02-28T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A practical handbook for optimizing open-source LLM inference using PagedAttention, FP8 quantization, and speculative decoding.]]></summary>
    <content type="html"><![CDATA[# Optimizing LLM Inference: Quantization, Speculative Decoding, and vLLM

Deploying open-weights LLMs like Llama-3, Qwen-2.5, or DeepSeek in production comes with strict latency and memory constraints. Unoptimized PyTorch models on raw GPUs quickly saturate VRAM and bottleneck token throughput.

Here is how we optimize LLM serving infrastructure to maximize tokens per second (TPS) while drastically reducing GPU hardware costs.

## PagedAttention and vLLM

The primary memory bottleneck during LLM inference is the Key-Value (KV) cache. Traditional implementations allocate contiguous VRAM blocks for KV cache per request, leading to massive memory fragmentation.

**vLLM** solves this with **PagedAttention**, dividing the KV cache into virtual memory pages:

```bash
# Launching high-throughput vLLM server with FP8 quantization and tensor parallelism
vllm serve meta-llama/Meta-Llama-3-70B-Instruct \
  --tensor-parallel-size 4 \
  --quantization fp8 \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.90
```

## Quantization: FP8 vs AWQ vs GGUF

- **FP8 (Floating Point 8)**: Native support on NVIDIA H100 and Ada Lovelace GPUs. Retains near 99.9% FP16 accuracy with 2x lower memory bandwidth usage.
- **AWQ (Activation-aware Weight Quantization)**: Ideal for 4-bit edge or lower VRAM deployments, preserving accuracy by prioritizing salient weight channels.

## Speculative Decoding for Latency Reduction

Speculative decoding pairs a small draft model (e.g. Llama-3-8B) with a large target model (e.g. Llama-3-70B). The draft model rapidly proposes token sequences, which the target model verifies in parallel in a single forward pass:

```python
# Speculative decoding setup in vLLM
from vllm import LLM, SamplingParams

llm = LLM(
    model="meta-llama/Meta-Llama-3-70B-Instruct",
    speculative_model="meta-llama/Meta-Llama-3-8B-Instruct",
    num_speculative_tokens=5,
)
```

Using speculative decoding yields a 1.8x - 2.4x speedup in generation latency without losing model performance.]]></content>
  </entry>
  <entry>
    <title>Building Production-Grade RAG Systems: From Vector Indexing to Hybrid Search</title>
    <link href="https://yahyaoncloud.com/blog/building-production-grade-rag-systems-hybrid-search"/>
    <id>https://yahyaoncloud.com/blog/building-production-grade-rag-systems-hybrid-search</id>
    <published>2026-02-14T00:00:00.000Z</published>
    <updated>2026-02-14T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A practical guide to building reliable RAG architectures using hybrid dense-sparse search, metadata filtering, and cross-encoder reranking.]]></summary>
    <content type="html"><![CDATA[# Building Production-Grade RAG Systems: From Vector Indexing to Hybrid Search

Retrieval-Augmented Generation (RAG) is often introduced as a simple two-step process: chunk your document, stick it into a vector database, and query an LLM. In real production workloads, naive vector search breaks down fast when dealing with domain terminology, part numbers, or exact keyword queries.

Here is the battle-tested architecture we use to deliver fast, highly accurate context to LLM models.

## The Limits of Pure Dense Vector Search

Dense embeddings (e.g., OpenAI text-embedding-3-small, BGE-large) capture semantic intent extremely well. However, they struggle with exact matching:

- Code identifiers and variable names
- Serial numbers and exact product codes
- Acronyms specific to your organization

When users search for `error_code_9021`, vector similarity might pull general error handling documents instead of the specific bug fix.

## Hybrid Search: Combining Dense Vector + BM25 Sparse Search

To solve this, we combine dense semantic search with sparse keyword search (BM25 or SPLADE) and rerank the combined results using a cross-encoder:

```python
# Example Hybrid Search pipeline using Qdrant & Reciprocal Rank Fusion (RRF)
def hybrid_search(query, top_k=10):
    # 1. Fetch dense vector results
    dense_results = qdrant_client.search(
        collection_name="docs",
        query_vector=get_embedding(query),
        limit=top_k * 2
    )
    
    # 2. Fetch sparse BM25 results
    sparse_results = bm25_index.search(query, top_k=top_k * 2)
    
    # 3. Combine scores using RRF
    combined_scores = reciprocal_rank_fusion(dense_results, sparse_results)
    
    # 4. Final reranking using Cohere or BGE Cross-Encoder
    final_docs = rerank(query, combined_scores[:top_k])
    return final_docs
```

## Key Takeaways for Production Deployment

1. **Chunking Strategy**: Avoid fixed-size character chunking. Use semantic chunking based on header boundaries or document sections.
2. **Metadata Filtering**: Always attach payload metadata (e.g. `tenant_id`, `category`, `created_at`) to narrow vector search spaces before executing dense comparisons.
3. **Cross-Encoder Reranking**: Re-ranking top candidates with a model like `bge-reranker-large` improves top-3 precision by over 30%.]]></content>
  </entry>
  <entry>
    <title>What the heck is Ansible anyways?</title>
    <link href="https://yahyaoncloud.com/blog/what-the-heck-is-ansible-anyways"/>
    <id>https://yahyaoncloud.com/blog/what-the-heck-is-ansible-anyways</id>
    <published>2026-01-19T00:00:00.000Z</published>
    <updated>2026-01-19T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[A beginner-friendly introduction to Ansible automation.]]></summary>
    <content type="html"><![CDATA[**What Is Ansible?**

Ansible is an open-source IT automation platform that enables you to automate configuration management, application deployment, provisioning, orchestration, and a wide range of routine IT tasks. Maintained by a large community and sponsored by Red Hat (which offers the commercial Red Hat Ansible Automation Platform), Ansible stands out for its simplicity, reliability, and minimal setup requirements.

Originally created in 2012 by Michael DeHaan and now one of the most widely adopted tools in DevOps and systems administration, Ansible allows teams to define infrastructure and processes as code—often described as "Infrastructure as Code" (IaC)—in a declarative, human-readable format.

### Core Characteristics

- **Agentless Architecture**  
  Ansible does not require any software agents or additional services to be installed on the target systems (managed nodes). It connects using standard protocols—primarily SSH for Linux/Unix systems and WinRM for Windows—meaning you can start automating existing servers immediately without preparation.

- **Push-Based Model**  
  From a central **control node** (typically your laptop, workstation, or a dedicated server), Ansible pushes small, temporary programs called **modules** to the managed nodes, executes them, and then removes them. Modules are idempotent: running the same task multiple times produces the same result without unintended side effects.

- **Declarative Language (YAML Playbooks)**  
  Automation logic is written in YAML files called **playbooks**. You describe the *desired state* of the system (e.g., "Nginx should be installed and running"), and Ansible ensures the system reaches and maintains that state. This contrasts with procedural scripting, making playbooks easier to read, review, and maintain—even for team members without deep programming experience.

- **Idempotency and Safety**  
  Tasks are designed to be repeatable and safe. If a server is already in the correct state, Ansible skips unnecessary changes, reducing risk during repeated runs or in production environments.

### Key Benefits

- **Simplicity** — YAML playbooks resemble structured English more than code. Minimal learning curve compared to tools requiring custom agents or complex DSLs.
- **No Agents** → Lower overhead, easier security compliance, and faster onboarding of new hosts.
- **Broad Applicability** — Manages Linux, Windows, network devices, cloud resources (AWS, Azure, GCP), containers, and more via thousands of community modules.
- **Extensibility** — Organized into **collections** (reusable bundles of modules, roles, and plugins) that are versioned and shareable via Ansible Galaxy.
- **Powerful Orchestration** — Handles multi-tier deployments, rolling updates, conditional logic, variables, loops, error handling, and event-driven automation.
- **Version Control Friendly** — Plain-text YAML files store perfectly in Git, enabling collaboration, auditing, and GitOps workflows.

### Simple Example: Installing and Starting Nginx

Here is a minimal playbook (`install_nginx.yml`) that ensures Nginx is installed and running on Debian/Ubuntu-based systems:

```yaml
---
- name: Install and configure Nginx
  hosts: webservers          # Target group from your inventory
  become: true               # Run tasks with sudo privileges

  tasks:
    - name: Install Nginx package
      ansible.builtin.apt:
        name: nginx
        state: present       # Ensures package is installed
        update_cache: yes

    - name: Ensure Nginx service is started and enabled
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true
```

To run it (assuming you have an inventory file listing hosts in the `webservers` group):

```bash
ansible-playbook install_nginx.yml
```

Ansible checks the current state, installs Nginx only if missing, starts the service if not running, and enables it to start on boot—all idempotently.

### Current Status (January 2026)

- The community project (ansible/ansible) is at **Ansible 12.x**, built on **ansible-core 2.19** (released mid-2025, with ongoing patch releases; 2.20 series GA in late 2025 and actively maintained).
- ansible-core 2.20 is the newest major line (GA November 2025), with full support through mid-2027.
- Red Hat Ansible Automation Platform (enterprise edition) is at version 2.6 with recent patch releases (January 2026), adding features like enhanced execution environments, security hardening, and UI-driven workflows.

### When to Use Ansible

Ansible shines in environments where you need to:
- Configure fleets of servers consistently
- Deploy applications reproducibly
- Automate repetitive admin tasks
- Manage hybrid/multi-cloud setups
- Implement zero-downtime rolling updates
- Replace manual SSH scripting or fragile Bash/Shell scripts

If you're managing even a handful of servers and find yourself repeating commands—or if you're building toward reliable, auditable infrastructure—Ansible can save significant time and reduce errors.

Official starting point: https://docs.ansible.com/ansible/latest/getting_started/index.html

Would you like guidance on installation, writing your first inventory and playbook, or how Ansible compares to tools like Terraform, Puppet, or Chef?]]></content>
  </entry>
  <entry>
    <title>Welcome to YahyaOnCloud</title>
    <link href="https://yahyaoncloud.com/blog/welcome-to-yahyaoncloud"/>
    <id>https://yahyaoncloud.com/blog/welcome-to-yahyaoncloud</id>
    <published>2026-01-19T00:00:00.000Z</published>
    <updated>2026-01-19T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[The official launch post for YahyaOnCloud blog platform.]]></summary>
    <content type="html"><![CDATA[# Welcome to YahyaOnCloud!

YahyaOnCloud is a space where I share practical experiences, ideas, and lessons around cloud engineering, infrastructure, networking, security, and modern development workflows.

Most of the content here will focus on real-world engineering topics — from designing cloud environments and managing infrastructure to working with automation, networking, monitoring, security operations, and scalable application deployments.

You can expect articles around:

* AWS and Azure infrastructure
* Cloud networking and hybrid environments
* Infrastructure security and operational hardening
* Terraform, automation, and CI/CD
* Remix, React, and backend development
* Monitoring and operational reliability
* Career growth in cloud and infrastructure roles

The goal is to keep the content practical, straightforward, and useful without unnecessary complexity or buzzwords. I’m more interested in discussing how systems actually operate in production than purely theoretical concepts.

Some posts will be technical deep dives, while others may cover engineering decisions, troubleshooting experiences, architecture discussions, operational security considerations, or lessons learned while building and maintaining systems.

Thanks for stopping by early. More content will be added regularly as the platform grows.]]></content>
  </entry>
  <entry>
    <title>Starting with Go Programming</title>
    <link href="https://yahyaoncloud.com/blog/starting-with-go-programming"/>
    <id>https://yahyaoncloud.com/blog/starting-with-go-programming</id>
    <published>2024-04-11T00:00:00.000Z</published>
    <updated>2024-04-11T00:00:00.000Z</updated>
    <summary type="html"><![CDATA[Deep dive into Golang basics and why it is the language of the cloud.]]></summary>
    <content type="html"><![CDATA[**Introduction to Go Programming**

Go, commonly referred to as Golang, is an open-source programming language developed by Google. First released in 2009, it was designed to address the challenges of existing languages such as C++ and Java by combining high performance, simplicity, and strong support for concurrent programming. Go is statically typed, compiled directly to machine code, and emphasizes readability, efficiency, and reliability.

As of January 2026, the current stable version is Go 1.25.6 (released January 15, 2026), which includes important security updates and bug fixes. Go 1.26 is in the release candidate stage and is expected to launch in February 2026, introducing refinements such as enhanced syntax flexibility (e.g., expanded use of the `new` built-in) and continued performance improvements.

### Why Choose Go?

Go remains a leading choice for modern software development due to several core strengths:

- **Performance**
 — Compiles to native binaries with minimal runtime overhead, delivering near-C-level execution speed and small, self-contained executables.
- **Concurrency Model** — Goroutines (lightweight threads managed by the runtime) and channels provide a straightforward, safe approach to concurrent programming, ideal for handling high-throughput workloads such as web servers and distributed systems.
- **Simplicity and Maintainability** — Features a clean, minimal syntax with no classes, inheritance, or complex generics overuse (generics, added in Go 1.18, are now mature and used judiciously). The language enforces consistent formatting via `gofmt`.
- **Standard Tooling** — Built-in support for dependency management (`go mod`), testing (`go test`), formatting, linting, and cross-compilation simplifies development workflows.
- **Ecosystem and Adoption** — Widely used in cloud infrastructure (Kubernetes, Docker, Prometheus), microservices, command-line tools, and DevOps applications. Demand for Go skills remains strong in backend, systems, and cloud-native roles.

Go excels in scenarios requiring scalability, low latency, and operational simplicity, making it particularly suitable for building reliable services and tools.

### Installation

Download the latest stable release from the official website: https://go.dev/dl/. Select the appropriate installer or archive for your operating system (Windows, macOS, Linux).

After installation, verify the setup by opening a terminal and running:

```bash
go version
```

This should display the installed version (e.g., `go version go1.25.6 ...`).

### Your First Program

Create a file named `hello.go` with the following content:

```go
package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}
```

Execute the program in two ways:

- Run directly (ideal for development):

  ```bash
  go run hello.go
  ```

- Build a standalone binary (produces an executable with no external dependencies):

  ```bash
  go build hello.go
  ./hello          # On Windows: hello.exe
  ```

This demonstrates Go's emphasis on straightforward compilation and deployment.

### Fundamental Concepts

#### Packages and Imports
Code is organized into packages. The `main` package defines the program entry point. Use `import` to access functionality from the standard library or third-party modules.

#### Variables and Constants
```go
var explicit string = "Declared with type"
inferred := 42               // Short declaration; type inferred as int
const MaxRetries = 5         // Constant (unchangeable)
```

#### Functions
Functions support multiple return values, a common pattern for error handling:

```go
func add(x, y int) int {
    return x + y
}

func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}
```

#### Control Structures
Go uses a single loop construct (`for`) and familiar `if`/`switch` statements:

```go
for i := 0; i < 10; i++ {
    // loop body
}

if condition {
    // ...
} else {
    // ...
}

switch value {
case 1, 2:
    // ...
default:
    // ...
}
```

#### Concurrency with Goroutines
Goroutines enable lightweight concurrency:

```go
package main

import (
    "fmt"
    "time"
)

func worker(id int) {
    fmt.Printf("Worker %d starting\n", id)
    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    for i := 1; i <= 3; i++ {
        go worker(i)  // Launch concurrently
    }
    time.Sleep(2 * time.Second)  // Wait for completion (production code would use sync.WaitGroup)
}
```

Channels provide safe communication between goroutines.

### Recommended Learning Path

1. Complete the interactive **A Tour of Go** (https://go.dev/tour/welcome/1) — an official, hands-on introduction (2–4 hours).
2. Review **Effective Go** (https://go.dev/doc/effective_go) for idiomatic practices.
3. Build small projects: a command-line tool, a basic HTTP server, or a concurrent data processor.
4. Study the book *The Go Programming Language* by Donovan and Kernighan for deeper understanding.
5. Engage with the community via the Go Forum, r/golang subreddit, or official Slack channels.
6. Explore modules (`go mod init`) and the standard library for real-world development.

Go's design prioritizes clarity and efficiency, allowing developers to produce robust software quickly. If you are interested in backend systems, cloud infrastructure, or high-performance applications, Go offers a powerful yet approachable foundation.

Should you have specific questions about installation, syntax, concurrency patterns, or project ideas, feel free to ask.]]></content>
  </entry>
</feed>