Day 1 — Setting Up Wassal v0: The Naive Monolith We'll Deliberately Break

# dotnet# distributedsystems# architecture# tutorial
Day 1 — Setting Up Wassal v0: The Naive Monolith We'll Deliberately Breakmohamed Tayel

Build Wassal v0 — a deliberately naive ASP.NET Core MVC monolith on .NET 8 + SQL Server — and tag it as the BEFORE state for the whole Fundamentals of Distributed Systems series.

Build the naive monolith we'll deliberately break in Lesson 1.

By the end of this hour, you'll have Wassal v0 running on your machine — a deliberately naive ASP.NET Core MVC monolith showing 5 restaurants from a SQL Server database, committed to git, and tagged as the BEFORE state for Lesson 1.

Here's the whole shape of what we're building today — one process, one database, no moving parts:

Wassal v0 — the Day-1 monolith stack

🎯 Today's goal: Wassal v0 running locally, committed, and tagged lesson-01-before. Six sequential tasks, ~50 minutes.


Task 1 — Verify Prerequisites (5 min)

Open PowerShell and confirm the three tools you'll need today are installed:

# .NET 8 SDK
dotnet --version    # expect 8.x.x

# Local SQL Server (full instance, Windows Auth)
sqlcmd -S "(local)" -E -Q "SELECT @@VERSION" -h -1

# Git
git --version
Enter fullscreen mode Exit fullscreen mode

💡 Missing something? Install via winget: winget install Microsoft.DotNet.SDK.8 · winget install Git.Git. SQL Server is assumed already installed locally (instance (local), Windows Auth).

✅ Done when: the sqlcmd call prints a version banner (e.g. "Microsoft SQL Server 2025 …"), and the other two commands return version numbers with no errors.


Task 2 — Initialize the Repository (10 min)

Navigate to the Wassal folder and initialize git:

cd D:\books\distributed-system\Wassal
git init
Enter fullscreen mode Exit fullscreen mode

Download a clean .NET .gitignore from the official Microsoft repo:

Invoke-WebRequest -Uri "https://raw.githubusercontent.com/dotnet/core/main/.gitignore" -OutFile ".gitignore"
Enter fullscreen mode Exit fullscreen mode

Create README.md at the root:

# Wassal — A Distributed Food Delivery Lab

A hands-on learning project to apply concepts from the
Fundamentals of Distributed Systems course.

Built as a series of Before → After lessons starting from
a naive monolith and evolving into a production-grade
distributed system.
Enter fullscreen mode Exit fullscreen mode

Commit:

git add .
git commit -m "chore: initial repo with docs and governance"
Enter fullscreen mode Exit fullscreen mode

✅ Done when: git log shows one commit and git status is clean.


Task 3 — Scaffold the .NET 8 MVC Solution (10 min)

Create the solution and the first project:

dotnet new sln -n Wassal
dotnet new mvc -n Wassal.Monolith -o src/Wassal.Monolith --framework net8.0
dotnet sln add src/Wassal.Monolith/Wassal.Monolith.csproj
dotnet build
Enter fullscreen mode Exit fullscreen mode

Expected layout after this step:

Wassal/
├── Wassal.sln
├── docs/                        (already exists)
├── src/
│   └── Wassal.Monolith/
│       ├── Controllers/
│       ├── Models/
│       ├── Views/
│       ├── Program.cs
│       └── Wassal.Monolith.csproj
└── README.md
Enter fullscreen mode Exit fullscreen mode

✅ Done when: dotnet build finishes with Build succeeded. 0 Warning(s) 0 Error(s).


Task 4 — Confirm Your Local SQL Server Is Reachable (2 min)

You already have a full local SQL Server instance ((local), SQL Server 2025) running and accessible via Windows Authentication. No setup needed today; we just confirm it's reachable from a shell so EF Core migrations will work in the next step.

# 1. Confirm the connection works
sqlcmd -S "(local)" -E -Q "SELECT @@SERVERNAME, @@VERSION" -h -1

# 2. Create the WassalDb database up front (idempotent)
sqlcmd -S "(local)" -E -Q "IF DB_ID('WassalDb') IS NULL CREATE DATABASE WassalDb;"
Enter fullscreen mode Exit fullscreen mode

💡 Why pre-create the DB? EF Core's database update will create it automatically if your user has the dbcreator role, but pre-creating it avoids permission edge cases on locked-down Windows boxes.

✅ Done when: the first sqlcmd call returns the server name + version banner, and the second completes silently.


Task 5 — Add EF Core, the Restaurant Entity, and Seed Data (15 min)

Add EF Core packages to the project:

cd src/Wassal.Monolith
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
cd ../..
Enter fullscreen mode Exit fullscreen mode

If you don't have the EF CLI tool installed globally yet:

dotnet tool install --global dotnet-ef
Enter fullscreen mode Exit fullscreen mode

Create the Restaurant modelsrc/Wassal.Monolith/Models/Restaurant.cs:

namespace Wassal.Monolith.Models;

public class Restaurant
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public string Cuisine { get; set; } = string.Empty;
    public string City { get; set; } = string.Empty;
    public decimal Rating { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Create the DbContext with seed datasrc/Wassal.Monolith/Data/WassalDbContext.cs:

using Microsoft.EntityFrameworkCore;
using Wassal.Monolith.Models;

namespace Wassal.Monolith.Data;

public class WassalDbContext(DbContextOptions<WassalDbContext> opts)
    : DbContext(opts)
{
    public DbSet<Restaurant> Restaurants => Set<Restaurant>();

    protected override void OnModelCreating(ModelBuilder b)
    {
        b.Entity<Restaurant>().HasData(
            new Restaurant { Id = 1, Name = "Koshary El Tahrir", Cuisine = "Egyptian", City = "Cairo", Rating = 4.6m },
            new Restaurant { Id = 2, Name = "Abou Tarek",        Cuisine = "Egyptian", City = "Cairo", Rating = 4.8m },
            new Restaurant { Id = 3, Name = "Burger Boutique",   Cuisine = "American", City = "Cairo", Rating = 4.3m },
            new Restaurant { Id = 4, Name = "Sushi Cairo",       Cuisine = "Japanese", City = "Cairo", Rating = 4.1m },
            new Restaurant { Id = 5, Name = "Pizza Hut",         Cuisine = "Italian",  City = "Giza",  Rating = 3.9m }
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Register the DbContext in Program.cs — add this before var app = builder.Build();:

using Microsoft.EntityFrameworkCore;
using Wassal.Monolith.Data;

// ... existing code ...

builder.Services.AddDbContext<WassalDbContext>(opts =>
    opts.UseSqlServer(
        "Server=(local);Database=WassalDb;" +
        "Trusted_Connection=true;TrustServerCertificate=true"));
Enter fullscreen mode Exit fullscreen mode

Create the database and run the migration:

dotnet ef migrations add InitialCreate --project src/Wassal.Monolith
dotnet ef database update --project src/Wassal.Monolith
Enter fullscreen mode Exit fullscreen mode

💡 Verify the data: in SSMS, expand WassalDbTablesdbo.Restaurants → "Select Top 1000 Rows" — you should see all 5 seeded rows.

✅ Done when: the database WassalDb exists and the Restaurants table has 5 seeded rows.


Task 6 — Render Restaurants + Commit + Tag the BEFORE State (10 min)

Replace the Index action in src/Wassal.Monolith/Controllers/HomeController.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Wassal.Monolith.Data;

public class HomeController : Controller
{
    public async Task<IActionResult> Index([FromServices] WassalDbContext db)
    {
        var restaurants = await db.Restaurants
            .OrderByDescending(r => r.Rating)
            .ToListAsync();
        return View(restaurants);
    }
}
Enter fullscreen mode Exit fullscreen mode

Replace the contents of src/Wassal.Monolith/Views/Home/Index.cshtml:

@model IEnumerable<Wassal.Monolith.Models.Restaurant>
@{ ViewData["Title"] = "Wassal — Restaurants"; }

<h1 class="display-5 mb-4">🍴 Restaurants in your city</h1>
<div class="row">
  @foreach (var r in Model)
  {
    <div class="col-md-4 mb-3">
      <div class="card shadow-sm">
        <div class="card-body">
          <h5 class="card-title">@r.Name</h5>
          <p class="text-muted mb-1">@r.Cuisine · @r.City</p>
          <span class="badge bg-warning text-dark">⭐ @r.Rating</span>
        </div>
      </div>
    </div>
  }
</div>
Enter fullscreen mode Exit fullscreen mode

Run the app from the repo root:

cd D:\books\distributed-system\Wassal
dotnet run --project src/Wassal.Monolith
Enter fullscreen mode Exit fullscreen mode

Open the URL printed in the console (typically https://localhost:5001). You should see 5 restaurant cards sorted by rating.

Stop the app (Ctrl+C), then commit and tag the BEFORE state:

git add .
git commit -m "feat: Wassal v0 monolith — list restaurants from SQL Server"
git tag v0-monolith-baseline
git tag lesson-01-before
Enter fullscreen mode Exit fullscreen mode

🏷️ Git tags in 60 seconds

A tag is a permanent bookmark on a specific commit. Unlike a branch (which moves forward as you commit), a tag freezes a moment in time. Think of commits as pages of a book, branches as your hand moving through them, and tags as sticky notes on important pages.

Throughout this series, every lesson sets two tags that mark its boundaries:

  • lesson-XX-before — the starting state (the "pain" we'll feel)
  • lesson-XX-after — the ending state (after applying the concept)

This lets you later run git diff lesson-01-before lesson-01-after to see exactly what changed, or git checkout lesson-01-before to revisit any snapshot.

git tag                       # list every tag in this repo
git tag NAME                  # create a tag on the latest commit
git checkout TAGNAME          # jump to that exact snapshot
git diff TAG1 TAG2            # see what changed between two tags
Enter fullscreen mode Exit fullscreen mode

✅ Done when: the browser displays 5 restaurant cards, git log --oneline shows two commits, and git tag lists both v0-monolith-baseline and lesson-01-before.


Quick Checklist

# Task Time Done When
1 Verify Prerequisites 5 min 3 versions print without errors
2 Initialize the Repo 10 min Initial commit exists
3 Scaffold .NET Solution 10 min dotnet build succeeds
4 Confirm Local SQL Server 2 min sqlcmd prints version + WassalDb created
5 EF Core + Seed 15 min 5 restaurants in DB
6 Render + Commit + Tag 10 min Browser shows cards, tags exist

🎓 Tomorrow's Preview

With Wassal v0 running and tagged as lesson-01-before, the next session installs k6, writes a load-test script, and watches the monolith collapse under 200 simulated users. That's the pain that gives meaning to every concept in the lessons that follow.


Part of the **Fundamentals of Distributed Systems* series — building Wassal, a distributed food-delivery lab, one concept at a time.*