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:
🎯 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
💡 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
Download a clean .NET .gitignore from the official Microsoft repo:
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/dotnet/core/main/.gitignore" -OutFile ".gitignore"
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.
Commit:
git add .
git commit -m "chore: initial repo with docs and governance"
✅ 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
Expected layout after this step:
Wassal/
├── Wassal.sln
├── docs/ (already exists)
├── src/
│ └── Wassal.Monolith/
│ ├── Controllers/
│ ├── Models/
│ ├── Views/
│ ├── Program.cs
│ └── Wassal.Monolith.csproj
└── README.md
✅ 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;"
💡 Why pre-create the DB? EF Core's
database updatewill create it automatically if your user has thedbcreatorrole, 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 ../..
If you don't have the EF CLI tool installed globally yet:
dotnet tool install --global dotnet-ef
Create the Restaurant model — src/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; }
}
Create the DbContext with seed data — src/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 }
);
}
}
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"));
Create the database and run the migration:
dotnet ef migrations add InitialCreate --project src/Wassal.Monolith
dotnet ef database update --project src/Wassal.Monolith
💡 Verify the data: in SSMS, expand
WassalDb→Tables→dbo.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);
}
}
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>
Run the app from the repo root:
cd D:\books\distributed-system\Wassal
dotnet run --project src/Wassal.Monolith
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
🏷️ 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
✅ 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.*

Top comments (0)