Generated by All in One SEO Pro v4.9.10, this is an llms.txt file, used by LLMs to index the site. # Chris Woody Woodruff | Fractional Architect ## Sitemaps - [XML Sitemap](https://woodruff.dev/sitemap.xml): Contains all public & indexable URLs for this website. ## Posts - [The N+1 Query Problem in EF Core: Detection, Diagnosis, and Permanent Fixes](https://woodruff.dev/the-n1-query-problem-in-ef-core/) - An order summary page renders in 40 milliseconds against your development database. The same page takes eleven seconds in production. You open the profiler, and the controller method looks clean. You reread the LINQ, and it reads correctly. You check the indexes, and every column you need is covered. The code passed review. The tests - [Add vs AddRange in EF Core: The Performance Myth You Need to Stop Repeating](https://woodruff.dev/add-vs-addrange-in-ef-core-the-performance-myth-you-need-to-stop-repeating/) - Somebody told you never to call Add() in a loop. Maybe it was a senior developer during code review. Maybe it was a Stack Overflow answer with four hundred upvotes. Maybe it was a blog post that ranks on page one for “improve entity framework performance.” The advice sounded authoritative: Add() forces a DetectChanges scan - [5 EF Core Performance Anti-Patterns That Entity Framework Extensions Eliminates](https://woodruff.dev/5-ef-core-performance-anti-patterns-that-entity-framework-extensions-eliminates/) - The Code You Already Wrote Every .NET team has at least one of these in production. It looked fine in review. It passed unit tests. It worked in staging against the seed data. Then real traffic hit, and now somebody is on call at three in the morning trying to work out why the nightly - [BulkSynchronize in EF Core: Mirror Your Data in One Operation](https://woodruff.dev/bulksynchronize-in-ef-core-mirror-your-data-in-one-operation/) - The Function Everyone Has Written, Nobody Loves If your codebase has a method called something like SyncProducts(), RefreshMetrics(), or UpdateFromFeed(), it probably looks something like this: // Load existing rows var existing = await context.Products .Where(p => p.SupplierId == supplierId) .ToListAsync(); // Build lookup for diffing var existingByKey = existing.ToDictionary(p => p.Sku); var incomingByKey = - [Scaling EF Core for Data Imports: From CSV Files to Millions of Database Rows](https://woodruff.dev/scaling-ef-core-for-data-imports/) - The Import Job Nobody Wants to Own Every team has one. It might be called an import service, a feed processor, or a sync job. The name varies. What stays constant is the shape of the problem: a large file arrives on schedule, and someone needs to get its contents into a database accurately, quickly, - [BulkMerge (Upsert) in EF Core: How to Insert-or-Update Without the Headache](https://woodruff.dev/bulkmerge-upsert-in-ef-core-how-to-insert-or-update-without-the-headache/) - Picture this. Your inbox lights up at 7:14 AM. A supplier just pushed 50,000 product records to your endpoint. Half are new. The other half are updates to products already sitting in your database. You have no idea which is which. The feed does not tell you. The records do not carry your internal primary - [New Release!! htmxRazor v2.1.0: Advanced Inputs](https://woodruff.dev/new-release-htmxrazor-v2-1-0-advanced-inputs/) - Forms are where server-rendered apps either feel sharp or feel clunky. A date field that drops you into a raw text box, a category selector that needs a client-side widget and three npm packages, a time field that accepts "2:74 pm" without complaint. Those are the rough edges that push teams toward heavy JavaScript pickers. - [EF Core Bulk Insert: The Complete Guide to Inserting Thousands of Rows Without the Wait](https://woodruff.dev/ef-core-bulk-insert-the-complete-guide-to-inserting-thousands-of-rows-without-the-wait/) - This post is sponsored by ZZZ Projects. You have written this loop. Every .NET developer has. foreach (var product in incomingProducts) { context.Products.Add(product); await context.SaveChangesAsync(); } It looks fine in a code review. It passes unit tests. It works against your local database with 200 sample rows in twelve milliseconds. Then production calls. The nightly - [Pagination in EF Core, Continued: Sortable Grids, htmx, and the Indexing Cost](https://woodruff.dev/pagination-in-ef-core-continued-sortable-grids-htmx-and-the-indexing-cost/) - The first post in this series made a clean case for keyset pagination over Skip/Take. Readers on LinkedIn pushed back with a fair question I'd dodged: what about sortable grids where the user picks the column? The post showed ORDER BY Id, which is the easy case. Real apps have grids with eight clickable column - [Pagination in Entity Framework Core: Why Skip/Take Falls Apart on Hot Tables](https://woodruff.dev/pagination-in-entity-framework-core-why-skip-take-falls-apart-on-hot-tables/) - If you've built an ASP.NET Core API or list view backed by Entity Framework Core, you've almost certainly written something like this: var page = await _db.Orders .OrderBy(o => o.Id) .Skip((pageNumber - 1) * pageSize) .Take(pageSize) .ToListAsync(); It works. It matches the page-number UI most users expect. Every EF Core tutorial uses it. It's also - [How to Delete and Update Millions of Rows in EF Core Without Loading a Single Entity](https://woodruff.dev/how-to-delete-and-update-millions-of-rows-in-ef-core-without-loading-a-single-entity/) - This post is sponsored by ZZZ Projects. The Code Every Developer Has Written and Regretted Most EF Core performance disasters are not exotic edge cases. They get written in the first sprint, look clean in code review, and only reveal themselves when row counts hit production scale. The pattern below has ended more than a - [ReSharper Made VS Code a Real Option for My .NET Work](https://woodruff.dev/resharper-made-vs-code-a-real-option-for-my-net-work/) - Most posts about ReSharper for VS Code want to convert you. This one doesn't. I write most of my .NET in Rider. I'm not moving. What changed for me back in March 2026, when JetBrains shipped the official ReSharper extension for VS Code, is something smaller and more useful than a conversion story. I can - [The Strategic Case for "Use What Works": Why Smart Tech Leaders Stop Reinventing the Wheel](https://woodruff.dev/the-strategic-case-for-use-what-works-why-smart-tech-leaders-stop-reinventing-the-wheel/) - A peculiar kind of pride runs through the technology industry. Many leaders believe their problems are unique, their scale unprecedented, their requirements so specific that only a custom-built solution will do. This belief is also one of the most expensive mistakes your organization can make. The Hidden Cost of "Building It Ourselves" Every custom solution - [htmxRazor v2.0.0: Platform and DX](https://woodruff.dev/htmxrazor-v2-0-0-platform-and-dx/) - An interactive playground, a live theme builder, SignalR, and a Kanban board, all on .NET 10 with no breaking changes. htmxRazor v2.0.0 is out today. The six features in this release span three distinct areas: developer tooling in your editor, interactive features on the demo site, and two new library components. This is the first - [htmxRazor v1.4.0: SSE Streaming, Multi-step Wizard, and Optimistic UI](https://woodruff.dev/htmxrazor-v1-4-0-sse-streaming-multi-step-wizard-and-optimistic-ui/) - v1.4.0 ships today with seven features built around a single theme: the interaction patterns real production applications actually need. Real-time content streaming, multi-step workflows, immediate UI feedback, response-aware forms, and a handful of targeted quality-of-life additions. SSE Stream wraps the htmx SSE extension declaratively. One Tag Helper, one server endpoint, no boilerplate: - [htmxRazor v1.3.0: Data Table, Accessibility, and Modern CSS](https://woodruff.dev/htmxrazor-v1-3-0-data-table-accessibility-and-modern-css/) - v1.3.0 lands today with six features organized around a clear theme: production patterns for .NET developers building server-rendered UIs that work correctly for everyone, including keyboard users and screen reader users. Here is what shipped. Data Table The data table is the feature request I hear most from .NET developers evaluating htmx. Until now there - [htmxRazor 1.2.0: Toast Notifications, Pagination, and the End of CSS Specificity Fights](https://woodruff.dev/htmxrazor-1-2-0-toast-notifications-pagination-and-the-end-of-css-specificity-fights/) - The first feature release after htmxRazor hit 1.1 is here, and it targets the three complaints I hear most from .NET developers building server-rendered apps with htmx: "I need toast notifications," "I need pagination that works with htmx from the start," and "your CSS keeps fighting with mine." Version 1.2.0 addresses all three. Here is - [Patterns of Distributed Systems in C# and .NET: A New Series for People Who Ship Real Systems](https://woodruff.dev/patterns-of-distributed-systems-in-c-and-net-a-new-series-for-people-who-ship-real-systems/) - Distributed systems do not fail because you missed a feature. They fail because responsibility is unclear. Two nodes act, both think they are right, and your data becomes a debate. This series is my pushback against cargo cult architecture. We are going to talk about the small, repeatable techniques that stop outages, not the buzzwords - [Fencing Tokens and Generation Clock in .NET: Stop Zombie Leaders From Writing](https://woodruff.dev/fencing-tokens-and-generation-clock-in-net-stop-zombie-leaders-from-writing/) - Leader election and leases answer a comforting question: who should be in charge right now. They do not fully answer the dangerous question: who can still write right now. A node can lose its lease, another node can become leader, and the old leader can still push writes through an existing database connection. When that - [Stop Wrestling with JavaScript: htmxRazor Gives ASP.NET Core the Component Library It Deserves](https://woodruff.dev/stop-wrestling-with-javascript-htmxrazor-gives-asp-net-core-the-component-library-it-deserves/) - Here is an uncomfortable truth the ASP.NET Core community has been avoiding for too long: server-rendered web development should not require you to adopt React, Vue, or Angular just to get a decent set of UI components. For years, .NET developers have been stuck choosing between two bad options. You can wire up Bootstrap by - [Lease Pattern in .NET: A Lock With an Expiration Date That Saves Your Data](https://woodruff.dev/lease-pattern-in-net-a-lock-with-an-expiration-date-that-saves-your-data/) - Indefinite locks belong to a world where processes never crash and networks never split. That world does not exist. In a distributed system, “I hold the lock” can mean “I held the lock before my VM paused for 45 seconds.” A lease fixes that by putting a deadline on ownership and forcing the owner to - [Leader Election in .NET: Picking One Boss Without Creating Two](https://woodruff.dev/leader-election-in-net-picking-one-boss-without-creating-two/) - If your service runs on more than one node and still has a single instance assumption, you already have leader election. You just do not have it on purpose. Leader election is the pattern that turns “somebody should run this” into “exactly one node is allowed to run this, and it must keep proving it - [Distributed System Pattern: Leader and Followers in .NET - One Decision Maker, Many Replicas, Fewer Outages](https://woodruff.dev/distributed-system-pattern-leader-and-followers-in-net-one-decision-maker-many-replicas-fewer-outages/) - Distributed systems rarely fail because you picked the wrong cloud service. They fail because two nodes believe they are in charge, both act, and both are “correct” from their own perspective. If your domain has any single authority assumption, and most systems do, you need a way to make that authority real. Leader and Followers - [Systems Thinking Meets Simplicity-First: A Decision Framework for Software Architects](https://woodruff.dev/systems-thinking-meets-simplicity-first-a-decision-framework-for-software-architects/) - Modern technology operates in a paradox. Our tools have never been more powerful, yet our systems have never felt more fragile. Every framework, pipeline, and process claims to simplify development, but most end up multiplying dependencies and eroding clarity. In that chaos, two guiding philosophies emerge: Systems Thinking and Simplicity-First. At first glance, they seem - [Enterprise Patterns for ASP.NET Core Minimal API: Data Transfer Object Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-data-transfer-object-pattern/) - Your domain model exists to protect your business rules.Your API exists to protect your clients. When you expose EF Core entities directly from your ASP.NET Core endpoints, you throw both of those protections away. The Data Transfer Object Pattern (DTO) is the line in the sand. DTOs carry data across boundaries. They flatten and optimize - [Stop Building SPAs for Every Screen: htmx + ASP.NET Core Razor Pages Workshop (Open)](https://woodruff.dev/stop-building-spas-for-every-screen-htmx-asp-net-core-razor-pages-workshop-open/) - If your default move for “modern UX” is a SPA, you are paying a tax you do not need. You pay for it in build pipelines, duplicated validation rules, fragile client state, and a front end that turns routine CRUD into an engineering project. This workshop is a different bet. We keep the server in - [Enterprise Patterns, Real Code: Implementing Fowler’s Ideas in C#](https://woodruff.dev/enterprise-patterns-real-code-implementing-fowlers-ideas-in-c/) - Most enterprise systems already use patterns from Martin Fowler’s Patterns of Enterprise Application Architecture. The twist is that many teams use them without naming them, half implement them and then wonder why the codebase fights back. If your ASP.NET solution contains controllers that talk straight to SQL, services that return HTTP responses, and entities that - [Enterprise Patterns for ASP.NET Core: Front Controller and MVC Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-front-controller-and-mvc-pattern/) - If every controller in your system does its own authentication, logging, and error handling, you do not have an architecture. You have a crowd of small frameworks pretending to cooperate. Front Controller and MVC are the patterns that push back against that drift. Front Controllers decide what every HTTP request must pass through. MVC decides what belongs - [Enterprise Patterns for ASP.NET Core Minimal API: Lazy Load Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-lazy-load-pattern/) - If a single endpoint pulls half your database just to render a small card on a mobile screen, your problem is not the database. Your problem is that you are afraid to say no. Lazy Load is how you say no. You refuse to pay for the cost of related data until it's actually needed. - [Enterprise Patterns for ASP.NET Core Minimal API: Identity Map Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-identity-map-pattern/) - If one customer quietly turns into three different in-memory objects during a single request, your domain is already lying to you. You see it when: Different parts of a request each load the same row again One instance is updated, another is validated, and a third is saved Bugs show up as “lost updates” or - [Enterprise Patterns for ASP.NET Core Minimal API: Unit of Work Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-unit-of-work-pattern/) - If a single business operation calls SaveChangesAsync three times, you do not have a transaction. You have a sequence of partial commits that you hope never fails in the middle. Think about a typical “Place Order” flow: Create an order Reserve inventory Update customer credit Write an audit log In many codebases, each step touches - [Enterprise Patterns for ASP.NET Core Minimal API: Repository Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-repository-pattern/) - If DbContext shows up in every corner of your codebase, you do not have a domain model. You have a thin layer of LINQ wrapped in HTTP. You see it when: Minimal API endpoints inject AppDbContext and write queries inline Domain services take DbContext instead of domain interfaces Every feature invents its own way to - [Debugging Entity Framework Core: 8 Real-World Query Anti‑Patterns (and How to Fix Them)](https://woodruff.dev/debugging-entity-framework-core-8-real-world-query-anti-patterns-and-how-to-fix-them/) - This is my post for the 2025 C# Advent. Check out all the great posts! I want to wish you a Merry Christmas, Happy Holidays, Happy Hanukkah, Happy Kwanzaa, and, finally, Happy Festivus. I will not be sharing my "Airing of grievances" or challenge anyone to a "Feats of strength." Entity Framework Core is an excellent - [Enterprise Patterns for ASP.NET Core Minimal API: Data Mapper Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-data-mapper-pattern/) - If every interesting class in your system secretly knows a connection string, your domain is not a model. It is a thin layer of code on top of a data access layer. You see it when: Domain classes inject DbContext directly Entities call SaveChanges on their own Simple rule tests require poking at a real - [Enterprise Patterns for ASP.NET Core Minimal API: Active Record Pattern](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-active-record-pattern/) - Sometimes, your domain is really just rows in a table. You have a Customers table with Id, Email, and CreditLimit.You load a row, tweak a field, and write it back.That is the whole story. In that situation, introducing a complete Domain Model, Data Mapper, and Repository stack can feel like ceremony for ceremony’s sake. The Active Record pattern exists for precisely this - [Enterprise Patterns for ASP.NET Core Minimal API: Service Layer Pattern - Making HTTP a Client, Not the Boss](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-service-layer-pattern-making-http-a-client-not-the-boss/) - Open a typical ASP.NET Core project, and you will often see the same shape: Controllers that validate input, construct entities and call several repositories Direct calls to external services (payments, credit, email) from controller actions Transactions managed in random places with SaveChangesAsync or manual transaction scopes If you have ever tried to add a second - [Enterprise Patterns for ASP.NET Core Minimal API: Domain Model Pattern - When Your Core Rules Deserve Their Own Gravity](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-domain-model-pattern-when-your-core-rules-deserve-their-own-gravity/) - Look at a typical enterprise ASP.NET Core application, and you often see the same pattern: Controllers validating requests, calculating totals, and applying discounts EF Core entities that are little more than property bags Stored procedures that quietly decide which orders are valid If you need to know how orders work, you do not open a - [Enterprise Patterns for ASP.NET Core Minimal API: Transaction Script Pattern - The Shortcut That Quietly Reshapes Your System](https://woodruff.dev/enterprise-patterns-for-asp-net-core-minimal-api-transaction-script-pattern-the-shortcut-that-quietly-reshapes-your-system/) - Picture this. Product wants a minor discount tweak: if an order total is below 100, no discount. You open an endpoint, add a conditional, save and push. Ten minutes, job done. Three months later, that simple rule exists in six different endpoints, each with its own tiny twist. Someone fixes a bug in two of - [Stop Letting Your Controllers Talk to SQL: Layered Architecture in ASP.NET Core](https://woodruff.dev/stop-letting-your-controllers-talk-to-sql-layered-architecture-in-asp-net-core/) - Walk into almost any long-lived enterprise codebase, and you will find the same pattern: Controllers that know about routing, JSON, SQL, and domain rules Repositories that reach up into HttpContext Business rules scattered across UI, stored procedures, and helper classes At that point, adding a new feature feels like surgery without a map. You poke at - [Licensing Compliance in the Courtroom: Why It Matters More Than You Think](https://woodruff.dev/licensing-compliance-in-the-courtroom-why-it-matters-more-than-you-think/) - If you're looking to enhance your organization's systems through quality assessments, I would love to connect with you. Let's explore how I can contribute to your success. You can easily reach me via my contact page here: https://woodruff.dev/contact/ In nearly every industry, open-source code fuels innovation. Developers harness open libraries, frameworks, and tools to accelerate - [Secure Application Development Starts With Architecture](https://woodruff.dev/secure-application-development-starts-with-architecture/) - If you're looking to enhance your organization's systems through quality assessments, I would love to connect with you. Let's explore how I can contribute to your success. You can easily reach me via my contact page here: https://woodruff.dev/contact/ Security cannot be patched in later; it is structural Most organizations still treat application security as part - [Bridging the Gap Between Software Engineering and Business Goals](https://woodruff.dev/bridging-the-gap-between-software-engineering-and-business-goals/) - If you're looking to enhance your organization's systems through quality assessments, I would love to connect with you. Let's explore how I can contribute to your success. You can easily reach me via my contact page here: https://woodruff.dev/contact/ Security cannot be patched in later; it is structural Many organizations underestimate the importance of incorporating security - [Make Your GitHub Profile Update Itself (WordPress posts, GitHub releases, LinkedIn newsletters)](https://woodruff.dev/make-your-github-profile-update-itself-wordpress-posts-github-releases-linkedin-newsletters/) - Want your GitHub profile to look alive without spending your weekends copy-pasting links? Let’s wire it to your actual work: blog posts from WordPress, newly published releases, and your newsletter issues. You will get a profile that quietly refreshes itself on a schedule and on events. We will use: A profile README repo (github.com//) A - [Software Quality Assessment as an Ongoing Practice, Not a One-Time Event](https://woodruff.dev/software-quality-assessment-as-an-ongoing-practice-not-a-one-time-event/) - If you're looking to enhance your organization's systems through quality assessments, I would love to connect with you. Let's explore how I can contribute to your success. You can easily reach me via my contact page here: https://woodruff.dev/contact/ Quality checks are often treated as a box to tick at release time Many organizations still think - [The Hidden ROI of Technical Due Diligence in Software Investments](https://woodruff.dev/the-hidden-roi-of-technical-due-diligence-in-software-investments/) - If you're looking to enhance your organization's ROI through strategic software investments, I would love to connect with you. Let's explore how I can contribute to your success. You can easily reach me via my contact page here: https://woodruff.dev/contact/ Most investment decisions focus on financials, not software foundations When investors assess a company, the starting - [Bringing Simplicity-First to the Page: My Upcoming Book](https://woodruff.dev/bringing-simplicity-first-to-the-page-my-upcoming-book/) - I am excited to share some big news. In the second half of 2026, my new book, titled Software Architecture Made Simple: A 'Simplicity-First' Approach to Software in the Age of Complexity, will be released. This book compiles years of blog articles, newsletters, and social media posts, consolidating them into a single, focused source of knowledge. - [System Modernization Without the Burnout: Lessons from Distributed Systems](https://woodruff.dev/system-modernization-without-the-burnout-lessons-from-distributed-systems/) - If you're looking for support in successfully migrating your legacy system, I would love to help your organization through this process. Let's connect and explore how I can assist you. You can contact me directly via my contact page here: https://woodruff.dev/contact/ The Dreaded “Big-Bang Rewrite” Every developer has heard the horror story: the company that - [Why Fractional Architecture is the Future of Technology Strategy](https://woodruff.dev/why-fractional-architecture-is-the-future-of-technology-strategy/) - If you’d like to chat about how I can help your organization as a Fractional Architect, I’d love to connect. You can reach me directly through my contact page here: https://woodruff.dev/contact/ Hook: The Myth of Big-Enterprise Architecture For years, software architecture has carried an aura of exclusivity, something reserved for Fortune 500 companies with expansive - [Day 35: Evolution Beyond Biology: Using Genetic Algorithms for Creative Art and Design](https://woodruff.dev/day-35-evolution-beyond-biology-using-genetic-algorithms-for-creative-art-and-design/) - Genetic Algorithms are often associated with engineering, scheduling, or optimization problems, but their potential extends into the domain of art and design. When applied to visual composition, generative structures, or music synthesis, GAs can produce unexpected and compelling outcomes. These creative applications demonstrate that evolution-inspired algorithms are not limited to purely functional results. In this - [Day 34: Genetic Algorithms vs. Other Optimization Techniques: A Developer's Perspective](https://woodruff.dev/day-34-genetic-algorithms-vs-other-optimization-techniques-a-developers-perspective/) - Genetic Algorithms (GAs) are a powerful optimization strategy inspired by the principles of natural evolution. But they are far from the only technique in a developer's toolbox. In this post, we will compare Genetic Algorithms with other widely-used optimization methods such as Gradient Descent, Simulated Annealing, and Particle Swarm Optimization. The goal is to understand - [Day 33: Case Study: Using a Genetic Algorithms to Optimize Hyperparameters in a Neural Network](https://woodruff.dev/day-33-case-study-using-a-genetic-algorithms-to-optimize-hyperparameters-in-a-neural-network/) - Tuning hyperparameters for machine learning models like neural networks can be tedious and time-consuming. Traditional grid search or random search lacks efficiency in high-dimensional or non-linear search spaces. Genetic Algorithms (GAs) offer a compelling alternative by navigating the hyperparameter space with adaptive and evolutionary pressure. In this post, we’ll walk through using a Genetic Algorithm - [Day 32: When Genetic Algorithms Go Wrong: Debugging Poor Performance and Premature Convergence](https://woodruff.dev/day-32-when-genetic-algorithms-go-wrong-debugging-poor-performance-and-premature-convergence/) - Even well-written Genetic Algorithms can fail. You might see little improvement over generations, results clustering around poor solutions, or a complete stall in progress. These symptoms often point to premature convergence, loss of genetic diversity, or flaws in selection and fitness evaluation. Debugging GAs requires tools, insight, and techniques for diagnosis and correction. Understanding Premature - [Day 31: Best Practices for Tuning Genetic Algorithm Parameters](https://woodruff.dev/day-31-best-practices-for-tuning-genetic-algorithm-parameters/) - Genetic Algorithms (GAs) are flexible and powerful tools for solving optimization problems. However, their effectiveness relies heavily on the correct tuning of parameters. Population size, mutation rate, crossover rate, selection pressure, and generation limits all affect convergence, solution quality, and performance. In today’s post, we will explore best practices for tuning these parameters to get - [Day 30: Unit Testing Your Evolution: Making Genetic Algorithms Testable and Predictable](https://woodruff.dev/day-30-unit-testing-your-evolution-making-genetic-algorithms-testable-and-predictable/) - Genetic Algorithms are inherently stochastic. Mutation introduces randomness. Crossover combines genes in unpredictable ways. Selection strategies often rely on probabilities. While this is essential to their power, it presents a challenge when it comes to unit testing. How can you reliably test behavior when the outcome changes on every run? The answer lies in isolating - [Day 29: Defining Interfaces for Genetic Algorithms Components: Fitness, Selection, and Operators](https://woodruff.dev/day-29-defining-interfaces-for-genetic-algorithms-components-fitness-selection-and-operators/) - To build flexible and maintainable genetic algorithm solutions in C#, a modular architecture is critical. Yesterday, we focused on designing a pluggable GA framework. Today, we take a deeper dive into how to structure the interfaces that allow different GA strategies to be easily swapped, tested, and reused. By defining clear contracts for fitness evaluation, - [Day 28: Building a Pluggable Genetic Algorithms Framework in C#](https://woodruff.dev/day-28-building-a-pluggable-genetic-algorithms-framework-in-c/) - As you reach the final week of our Genetic Algorithms series, it is time to shift from experimentation to engineering. Instead of writing one-off implementations tailored to specific problems, the focus now turns to creating a flexible and pluggable genetic algorithm (GA) framework. This architecture allows developers to reuse core evolutionary components across different problem - [Day 7: Putting It Together: Simulating Your First Genetic Algorthm Cycle in .NET](https://woodruff.dev/day-7-putting-it-together-simulating-your-first-ga-cycle-in-net/) - By now, you’ve learned the foundational components of genetic algorithms: chromosomes, genes, fitness functions, mutation, crossover, and selection. Today, it’s time to bring those elements together and run your first complete GA cycle using C# and .NET. This post walks you through the structure of a single evolutionary loop—initialization, evaluation, selection, reproduction, and mutation—so you can simulate a working genetic algorithm and evolve real solutions. - [Day 19: Scheduling with DNA: Using Genetic Algorthms for Class and Work Timetables](https://woodruff.dev/day-19-scheduling-with-dna-using-gas-for-class-and-work-timetables/) - Scheduling is a classic example of a constraint satisfaction problem that often becomes too complex for brute-force or greedy solutions. Whether you're designing class timetables for a university or shift schedules for employees, the number of constraints quickly increases, making traditional methods inefficient. Genetic Algorithms provide a flexible and powerful approach to finding feasible and optimized schedules by evolving solutions that balance multiple constraints over time. In a scheduling problem, the chromosome represents a potential timetable. Each gene can represent a time-slot assignment for a course, instructor, room, or shift. Unlike simple optimization problems, scheduling must respect both hard constraints (such as no double-booking of rooms or overlapping classes for a teacher) and soft constraints (such as preferring certain time blocks). - [Day 26: Running Genetic Algorthms in the Cloud with Azure Batch or Functions](https://woodruff.dev/day-26-running-gas-in-the-cloud-with-azure-batch-or-functions/) - As your genetic algorithm workloads grow in complexity, compute-intensive tasks like evaluating large populations or running many generations can exceed what a single machine can handle efficiently. To address this, cloud platforms such as Microsoft Azure offer scalable execution environments where GAs can be deployed and run in parallel. Azure Batch and Azure Functions are two effective approaches to execute genetic algorithms at scale, each suited to different execution patterns. - [Day 27: Logging and Monitoring Genetic Algorthms Progress Over Generations](https://woodruff.dev/day-27-logging-and-monitoring-genetic-progress-over-generations/) - As your genetic algorithms become more sophisticated, it's no longer enough to simply observe the final output. Monitoring the evolutionary process in real time provides critical insight into convergence behavior, mutation impacts, and solution quality. Logging and monitoring allow you to diagnose performance bottlenecks, identify premature convergence, and validate the impact of parameter changes. - [Day 25: Scaling Up: Parallelizing Genetic Algorithms Loops in .NET with Parallel.ForEach](https://woodruff.dev/day-25-scaling-up-parallelizing-genetic-algorithms-loops-in-net-with-parallel-foreach/) - As problem complexity grows, so does the cost of evaluating and evolving populations in genetic algorithms. When each individual's fitness computation becomes expensive or the population size increases substantially, runtime performance can become a serious bottleneck. Fortunately, .NET makes it easy to scale genetic algorithms with minimal code changes by using Parallel.ForEach. - [Day 24: Combining Genetic Algorithms with Hill Climbing: The Hybrid Memetic Approach](https://woodruff.dev/day-24-combining-genetic-algorithms-with-hill-climbing-the-hybrid-memetic-approach/) - Traditional genetic algorithms (GAs) excel at global exploration across large search spaces. However, they can struggle to fine-tune solutions with high precision due to their stochastic nature. On the other hand, local search techniques like hill climbing are good at refining individual solutions but easily get trapped in local optima. A memetic algorithm combines both approaches, using GAs for exploration and local search for exploitation. This hybrid strategy has proven effective in complex optimization problems where both breadth and depth of search are required. - [Day 23: Introduction to Non-dominated Sorting Genetic Algorithm II (NSGA-II) in C#](https://woodruff.dev/day-23-introduction-to-non-dominated-sorting-genetic-algorithm-ii-nsga-ii-in-c/) - As we extend our use of genetic algorithms (GAs) beyond single-objective problems, we enter the realm of multi-objective optimization, where trade-offs must be made between competing goals. The Non-dominated Sorting Genetic Algorithm II (NSGA-II) is one of the most widely used algorithms for solving such problems. Its design maintains a diverse population of high-quality solutions that form what is known as a Pareto front. - [Day 22: Multi-Objective Optimization: When One Fitness Function Isn't Enough](https://woodruff.dev/day-22-multi-objective-optimization-when-one-fitness-function-isnt-enough/) - In many real-world problems, a single fitness function is insufficient to capture the complexity of the solution space. Applications in engineering, logistics, finance, and machine learning often involve trade-offs among competing objectives. For example, minimizing cost while maximizing performance, or reducing power consumption without sacrificing accuracy. In these cases, genetic algorithms (GAs) can be extended to support multi-objective optimization. - [Day 15: Fitness by Design: How to Shape the Problem to Match Evolution](https://woodruff.dev/day-15-fitness-by-design-how-to-shape-the-problem-to-match-evolution/) - In genetic algorithms, the fitness function is not just a scoring system—it is the definition of success. Your entire evolutionary process hinges on how well the fitness function communicates what "better" means in the context of your problem. If the fitness function rewards the right behaviors, your algorithm will evolve meaningful solutions. If not, you may end up optimizing toward the wrong objective or stuck in a plateau of mediocrity. This post focuses on how to design fitness functions that align with your goals, reflect nuanced problem definitions, and promote useful evolution. Whether you are evolving strings, optimizing numbers, or solving real-world configurations, the fitness function is where the problem and solution space meet. - [Day 16: Solving the Traveling Salesperson Problem with Genetic Algorithms Permutation Chromosomes](https://woodruff.dev/day-16-solving-the-traveling-salesperson-problem-with-genetic-algorithms-permutation-chromosomes/) - The Traveling Salesperson Problem, also known as TSP, is one of the most extensively studied combinatorial optimization problems in computer science. Given a set of cities and the distances between them, the objective is to find the shortest possible route that visits each city exactly once and returns to the starting point. This problem is computationally difficult to solve using brute-force methods because the number of possible routes grows factorially with the number of cities. - [Day 17: Greedy Isn't Always Bad: Heuristics in Genetic Algorithms](https://woodruff.dev/day-17-greedy-isnt-always-bad-heuristics-in-genetic-algorithms/) - Genetic algorithms thrive on randomness and gradual improvement, but randomness alone often leads to slow convergence. While global search is essential to explore the full solution space, local improvements can dramatically accelerate progress. That is where heuristics come into play. Specifically, greedy heuristics can guide genetic algorithms by introducing problem-specific knowledge that favors better starting points, smarter offspring, and faster convergence. - [Day 20: Constraint Handling in Fitness Functions: Penalizing Bad Solutions](https://woodruff.dev/day-20-constraint-handling-in-fitness-functions-penalizing-bad-solutions/) - Genetic algorithms are powerful optimization tools, but real-world problems often involve constraints that cannot be ignored. In scheduling, routing, resource allocation, and layout optimization, constraints like resource limits, timing conflicts, and exclusivity rules define what makes a solution valid. Without a mechanism to enforce or guide adherence to these rules, a genetic algorithm may evolve highly fit but completely infeasible solutions. One effective way to handle this is by integrating constraint penalties directly into the fitness function. By penalizing violations, we make sure that invalid solutions are less likely to survive and propagate in future generations. This method requires designing fitness functions that are both accurate evaluators and adaptive enforcers of your problem's rules. - [Day 21: Genetic Algorithms vs. Brute Force: A Benchmark Comparison](https://woodruff.dev/day-21-genetic-algorithms-vs-brute-force-a-benchmark-comparison/) - To conclude Week 3, let’s address one of the most common questions developers ask when learning about genetic algorithms: How do they perform compared to brute-force solutions? This is especially relevant when working on combinatorial problems, such as the Traveling Salesperson Problem (TSP) or scheduling tasks. Genetic algorithms promise that they offer reasonable solutions in a fraction of the time it takes brute-force methods to find optimal ones. But how does this actually play out? Today, we’ll benchmark a simple scenario using both approaches and compare execution time and solution quality. We’ll use the TSP with 8 cities as our problem space. This size is large enough to make brute-force non-trivial, but still solvable within a reasonable time. - [Day 14: Evolving Text: Solving the "Hello World" Puzzle with a C# Genetic Algorithm](https://woodruff.dev/day-14-evolving-text-solving-the-hello-world-puzzle-with-a-c-genetic-algorithm/) - Now that you’ve built the complete set of genetic algorithm components, chromosomes, fitness functions, mutation, crossover, selection, and a configurable loop, it’s time to apply everything in a hands-on project. In today’s post, we’ll use a genetic algorithm to evolve a string toward a target phrase: "HELLO WORLD". This classic exercise helps demonstrate how genetic algorithms work in a tangible, visual way. You’ll see the population of strings gradually improve, letter by letter, until they match the target. It’s a powerful example of emergent behavior through selection and variation. - [Day 18: Mapping Cities: Visualizing TSP Evolution in .NET](https://woodruff.dev/day-18-mapping-cities-visualizing-tsp-evolution-in-net/) - One of the most effective ways to understand the progress of a genetic algorithm is to visualize its evolution. When solving the Traveling Salesperson Problem, a well-designed visualization can clearly show how random routes evolve into efficient paths over time. In .NET, we can use simple drawing libraries like System.Drawing to generate visual output during the evolution process. Today, we will walk through how to integrate a visual component into your genetic algorithm for TSP using permutation chromosomes. You will generate images that show the route taken by the best chromosome of each generation, allowing you to see improvement over time. - [Day 13: Configuring the Genetic Algorithm Loop in C#](https://woodruff.dev/day-13-configuring-the-genetic-algorithm-loop/) - A genetic algorithm is only as effective as the loop that drives it. While selection, crossover, mutation, and elitism form the backbone of a genetic algorithm (GA), it is the configuration of the evolution loop that determines how the algorithm behaves over time. Today’s focus is on designing and implementing the loop that runs your genetic algorithm. We will examine how to parameterize the loop with values such as population size, mutation rate, elite count, and maximum generations, and how to structure your logic to support reusable, testable, and adaptable evolutionary flows in C#. - [Evolve Your C# Code with AI: A 5-Week Genetic Algorithms Bootcamp for Developers](https://woodruff.dev/evolve-your-c-code-with-ai-a-5-week-genetic-algorithms-bootcamp-for-developers/) - What if your code could evolve like life itself—adapting, optimizing, and learning over time? Welcome to the AI-inspired world of Genetic Algorithms, where we blend evolution with code to solve complex problems cleverly. Starting this week, I'm launching a 42-day blog series—a 4-week bootcamp—designed to teach C# and .NET developers how to build, run, and scale Genetic Algorithms. From foundational concepts to solving real-world optimization problems, this series is your guide to coding like Darwin meant it. Using clean, testable C# code, we'll simulate survival of the fittest with fitness functions, crossover operations, mutations, and elite selection. This isn't theoretical fluff—it's practical, hands-on AI for your everyday dev life. Whether you're optimizing routes, building smarter schedules, or just curious how to make your software think, this series is for you. - [Day 12: Genetic Algorithms' Elitism for Evolution Survival of the Fittest](https://woodruff.dev/day-12-genetic-algorithms-elitism-for-evolution-survival-of-the-fittest/) - Natural selection favors the survival of the fittest, but evolution in the wild is not always efficient. In genetic algorithms, we can bias the process toward faster convergence by deliberately preserving top-performing individuals across generations. This technique is known as elitism, and it is one of the simplest yet most effective strategies for enhancing GA performance. Today’s post focuses on applying elitism in a C# genetic algorithm to ensure that the best solutions are never lost. We will define elitism, explain its impact on the evolutionary process, and demonstrate how to implement it cleanly and effectively. - [Day 11: Implementing a C# Mutation Operator for Genetic Algorithms](https://woodruff.dev/day-11-implementing-a-c-mutation-operator-for-genetic-algorithms/) - In yesterday’s post, we explored the importance of mutation in genetic algorithms. Mutation helps maintain genetic diversity, prevent premature convergence, and enable the discovery of better solutions through small, random changes. Today, we shift from theory to implementation. Our goal is to code a mutation operator in C# that is both configurable and adaptable to different types of chromosomes. This operator will be a core component of your genetic algorithm loop, introducing the right level of randomness into your evolutionary process. - [Day 10: Mutation Matters in C# Genetic Algorithms](https://woodruff.dev/day-10-mutation-matters-in-c-genetic-algorithms/) - In biological evolution, mutations are rare, random changes in DNA that introduce new traits. While many mutations are neutral or even harmful, some spark evolutionary leaps. In genetic algorithms, mutation serves the same purpose: injecting fresh variations into the population to avoid stagnation and premature convergence. Without mutation, a genetic algorithm can easily fall into local optima—improving early on but plateauing before reaching the best solution. Mutation helps keep the algorithm dynamic, ensuring exploration continues even when the population becomes homogeneous. Today, we explore how mutation works, its importance in the evolutionary process, and how to implement it in C#. - [Day 9: Using Genetic Algorithm's Uniform Crossover in C#](https://woodruff.dev/day-9-using-genetic-algorithms-uniform-crossover-in-c/) - So far, we’ve explored one-point and two-point crossover strategies, which split chromosomes at predefined positions. These methods are effective for maintaining gene sequence structure, but they can be limiting when diversity is crucial. Enter uniform crossover—a technique that treats each gene position independently, offering greater mixing and a finer-grained approach to recombination. Today, we’ll implement uniform crossover in C#, compare it with other strategies, and explore when and why you should use it. - [Day 8: One Point or Two? How Crossover Shapes Genetic Diversity](https://woodruff.dev/day-8-one-point-or-two-how-crossover-shapes-genetic-diversity/) - In the evolutionary process, crossover is the mechanism by which parents pass on their traits to offspring. In genetic algorithms, crossover plays the same role, combining genes from two parent chromosomes to produce new solutions. How you implement crossover significantly impacts the algorithm's ability to explore the search space and avoid premature convergence. Today, we dive into crossover methods in C#, comparing one-point, two-point, and uniform crossover, and how each influences genetic diversity. - [Day 6: Roulette, Tournaments, and Elites: Exploring Selection Strategies](https://woodruff.dev/day-6-roulette-tournaments-and-elites-exploring-selection-strategies/) - Once you’ve calculated the fitness of each chromosome in your population, the next step in the genetic algorithm lifecycle is selection—deciding which chromosomes get to reproduce and which are left behind. Selection strategies play a crucial role in balancing exploration (searching new areas of the solution space) and exploitation (refining known good solutions). Choosing the right strategy affects the convergence speed and the overall effectiveness of your genetic algorithm. Today, we’ll explore the most common selection strategies: roulette wheel selection, tournament selection, and elitism. We’ll compare them and implement each one in C#. - [Day 5: Natural Selection in Software: Implementing Fitness Functions](https://woodruff.dev/day-5-natural-selection-in-software-implementing-fitness-functions/) - In the natural world, organisms survive and reproduce based on their ability to adapt to their environment. This principle of natural selection is central to the effectiveness of genetic algorithms. In software, our analog to survival is fitness—a quantitative measurement of how well a solution performs. Today, we focus on the role of fitness functions in guiding evolutionary progress in a genetic algorithm, and we’ll implement them in C# to evaluate and score candidate solutions effectively. - [Day 4: Designing Your First Chromosome Class in C#](https://woodruff.dev/day-4-designing-your-first-chromosome-class-in-c/) - Now that we’ve explored the concept of genes and chromosomes in the context of genetic algorithms, it’s time to write some real code. Today’s goal is to design a reusable, extensible Chromosome class in C# that can serve as the foundation for solving optimization problems using genetic algorithms. We will not only model the chromosome itself, but also lay the groundwork for operations such as initialization, crossover, mutation, and evaluation. Think of this class as the central actor in your evolutionary simulation. - [Day 3: Understanding Chromosomes, Genes, and DNA in Code](https://woodruff.dev/day-3-understanding-chromosomes-genes-and-dna-in-code/) - At the heart of every genetic algorithm lies the concept of evolution, and at the heart of evolution lies DNA. For software developers, the equivalent building blocks are chromosomes and genes. If we want our applications to evolve solutions over time, we need a reliable way to encode, manipulate, and assess those building blocks in our C# programs. Today, we’ll take a closer look at how we can represent chromosomes and genes in C#, how to choose the right data structures, and how to build a model that is both flexible and performant. - [Mechanical Minds and Human Folly: Why Fearin' AI is More Foolish Than Fruitful](https://woodruff.dev/mechanical-minds-and-human-folly-why-fearin-ai-is-more-foolish-than-fruitful/) - It has come to my attention recently that many good folks have grown anxious over this new contrivance known as Artificial Intelligence. They eye these ingenious machines with suspicion, fearing we might soon become servants to mechanical overlords. Please permit me to offer a few thoughts on this subject, not to dispel your apprehensions outright but rather to restore a measure of good sense and clear perspective. - [Day 2: Evolution in Code: The Core Concepts](https://woodruff.dev/day-2-evolution-in-code-the-core-concepts/) - At their core, genetic algorithms are built on five foundational principles that closely resemble biological evolution: 1. Genes and Chromosomes In biology, genes are units of information, and chromosomes are structured collections of those genes. In GAs, a chromosome is a single candidate solution, typically represented as an array, list, or string. Each gene in - [Rust Scalar and Compound Types: Where Are My C# Classes?](https://woodruff.dev/rust-scalar-and-compound-types-where-are-my-c-classes/) - When I first started exploring Rust, one of my instincts was to reach for a class. You know the drill. Need to model some data? Write a class, slap a few properties on it, and maybe add a constructor or two. But Rust had other plans. On Day 6, I dug into Rust’s scalar and compound types and quickly realized that Rust doesn’t want you to start with classes. Instead, it hands you a small set of powerful primitives and says, “Let’s build something lean.” - [Day 1: The Survival of the Fittest Code: Why Learn Genetic Algorithms in C#?](https://woodruff.dev/day-1-the-survival-of-the-fittest-code-why-learn-genetic-algorithms-in-c/) - What if you could write code that evolves? Not just code that runs, but code that iteratively improves its own solutions to complex problems without requiring you to handcraft every edge case. That’s the promise of genetic algorithms (GAs), an AI-inspired method rooted in Darwinian evolution, and it fits surprisingly well in the world of modern C# development. - [From C# to Rust: A 42-Day Developer Challenge](https://woodruff.dev/from-c-to-rust-a-42-day-developer-challenge/) - I’ve spent over a decade writing C# and building solutions on .NET. But for six weeks, we will step outside the managed world of garbage collection and runtime JIT to dive headfirst into Rust—a systems programming language that promises performance, safety, and no nulls. Over the course of 42 days, we will learn something new about Rust every single day. We will fight the borrow checker. We will make mistakes. And I will blog it all from the perspective of a C# developer trying to make sense of it. - [Performance Check: Does Rust Really Fly?](https://woodruff.dev/performance-check-does-rust-really-fly/) - Welcome to Day 41, and we are almost done! Today, we are putting Rust’s performance reputation to the test. Rust has a reputation for being fast. But how fast? If you have been living in the C# world where the JIT and garbage collector handle things for you this is a good chance to see how Rust stacks up when it comes to raw speed. - [Final Reflections: What Rust Taught Me as a C# Dev](https://woodruff.dev/final-reflections-what-rust-taught-me-as-a-c-dev/) - Day 42, and here we are. Six weeks of learning Rust from the perspective of a C# developer. We covered the basics, wrestled with ownership, danced with traits and lifetimes, and shipped a working CLI app. Along the way, there were moments of frustration, lightbulb moments, and more than a few “why is this so hard” conversations with the compiler. This final reflection is about stepping back and asking the big questions. What did Rust really teach me? What am I taking back to my C# projects? What might be next? - [Packaging and Releasing a Rust CLI Tool](https://woodruff.dev/packaging-and-releasing-a-rust-cli-tool/) - Day 40, and today we are looking at how to package and release your Rust CLI app. You have written the code, added argument parsing, handled the logic, and even written tests. Now it is time to get that shiny CLI tool into the hands of others. This process will feel familiar if you have worked with .NET global tools. Rust’s cargo makes it easy to build, release, and share your command-line apps. - [Writing Tests in Rust: Familiar and Fast](https://woodruff.dev/writing-tests-in-rust-familiar-and-fast/) - Onward to Day 39. Today, we're discussing testing in Rust. If you are a C# developer, you have probably spent time with xUnit, NUnit, or MSTest. You know the usual [TestMethod] or [Fact] attributes and Assert.Equal calls. Rust’s testing system is going to feel pretty familiar with a bit of Rust flair. - [Working with Files and the Filesystem in Rust](https://woodruff.dev/working-with-files-and-the-filesystem-in-rust/) - Welcome to Day 38. Today, we're getting our hands dirty with file I/O. Reading and writing files is one of those tasks every app must perform at some point. If you have written C# code using System.IO this is going to feel familiar but with a Rust twist. - [Parsing Arguments and Writing Logic in Rust](https://woodruff.dev/parsing-arguments-and-writing-logic/) - We are up to Day 37, and today, we are continuing to build out our Rust CLI app. Last time, we set up a simple command-line tool using the clap crate. Now, it is time to dig a little deeper into parsing arguments, handling input validation, and structuring our logic cleanly. If you are coming from the C# world, this is where you would probably set up your Program.cs to parse args[], maybe use a library like CommandLineParser, and then branch out into your application logic. Rust gives you similar tools but with its own flavor. - [Building a CLI App in Rust: My First Project](https://woodruff.dev/building-a-cli-app-in-rust-my-first-project/) - It's day 36, and today, we are shifting gears from theory to practice. It is time to roll up our sleeves and build something. If you have ever built a command-line tool in C# using .NET Console apps, you will feel right at home. Rust has the same capability with a few extras that make the experience feel pretty slick. - [Lifetimes: Surviving the First Encounter](https://woodruff.dev/lifetimes-surviving-the-first-encounter/) - Day 32, and today we are stepping into one of Rust’s most talked-about features. If you have heard scary stories about lifetimes, do not worry. This is your first encounter, and we are going to make it approachable. If you are coming from C#, the idea of lifetimes might feel strange at first. In .NET you lean on the garbage collector to handle memory cleanup. You create objects, and when they are no longer needed, the GC comes along and takes out the trash. Rust does not have a garbage collector. It uses ownership and borrowing to manage memory. Lifetimes are how Rust keeps track of how long references are valid. They are the glue that ties Rust’s memory safety model together. - [Week 5: Reflecting on Traits & Lifetimes Power and Pain](https://woodruff.dev/week-5-reflecting-on-traits-lifetimes-power-and-pain/) - You've made it to Day 35, and we're wrapping up Week 5. This week was all about Rust’s generics, contracts, and lifetimes. If your brain feels like it has been doing deadlifts, that means you are doing it right. Traits and lifetimes bring a lot of power to Rus,t but they can also make your head spin if you are used to the more relaxed rules of C#. Let us take a moment to look back on what we covered and how Rust compares to what you might be used to with C#. - [Rust Iterators and Functional Combinators](https://woodruff.dev/iterators-and-functional-combinators/) - Welcome to Day 34, and today we are taking a stroll through one of the most satisfying parts of Rust. If you're a C# developer who loves LINQ, this will feel like home, with just enough Rust flavor to keep it interesting. - [Closures in Rust: Functional Vibes with a Twist](https://woodruff.dev/closures-in-rust-functional-vibes-with-a-twist/) - Welcome to Day 33, and today we are jumping into closures. If you have been writing C# for a while, you are no stranger to lambdas, delegates, and maybe even expression trees. Rust has closures, too, and they bring a nice functional flavor to the language with some unique Rust twists. - [Generics in Rust vs Generics in C#](https://woodruff.dev/generics-in-rust-vs-generics-in-c/) - Welcome to Day 31, and today we are diving into generics. If you are coming from C# this is probably familiar ground. You know and love List, Dictionary, and all the type-safe goodness that generics bring to your code. Rust has generics too but with a twist. The syntax might look similar but Rust’s approach gives you some extra control and a few new things to think about. - [Trait Objects: Goodbye virtual, Hello dyn](https://woodruff.dev/trait-objects-goodbye-virtual-hello-dyn/) - Welcome to Day 30 and today we are going to explore how Rust handles dynamic dispatch with trait objects. If you are used to the world of C# this is the part where you usually reach for abstract classes or virtual methods. Maybe you sprinkle in some interfaces and let polymorphism do the heavy lifting at runtime. In Rust dynamic dispatch works a little differently and it is all thanks to dyn. - [Traits in Rust: Interfaces That Do More](https://woodruff.dev/traits-in-rust-interfaces-that-do-more/) - Welcome to Day 29 where we are stepping into one of Rust’s most powerful features. If you are a C# developer think of traits as interfaces but with some serious upgrades. Traits in Rust define shared behavior just like interfaces do in C#. But Rust’s approach feels more flexible and composable. - [Week 4: Reflecting on Errors and Structure](https://woodruff.dev/week-4-reflecting-on-errors-and-structure/) - Day 28 marks the end of Week 4 and it is time to pause for a quick reflection. We have covered a lot of ground this week from organizing Rust code with modules and crates to handling errors with grace instead of chaos. Coming from a C# background this week might have felt both familiar and refreshingly different. - [Logging in Rust: Tracing Without Console.WriteLine](https://woodruff.dev/logging-in-rust-tracing-without-console-writeline/) - Welcome to Day 27 and let’s talk about how Rust handles logging the smart way. If you have been in the .NET world for any amount of time, you are probably used to ILogger. You know the drill: inject a logger, use it throughout your code, and stay away from the quick and dirty Console.WriteLine scattershot approach. Rust takes a similar path but with its own flavor. It gives you the log and tracing crates, both designed to keep your code clean while still giving you rich, structured log output when you need it. - [Custom Errors: From Display to thiserror](https://woodruff.dev/custom-errors-from-display-to-thiserror/) - Look at this! Day 26, and today we’re talking about one of my favorite things to not ignore: error messages. Because when things go sideways (and they will), your future self and your users will appreciate error handling that’s clear, structured, and helpful. - [Panic! vs Exceptions: Stop the World or Handle It?](https://woodruff.dev/panic-vs-exceptions-stop-the-world-or-handle-it/) - Okay, we're on Day 25, and today we’re stepping into the world of failure again. But this time, it’s the catastrophic kind. We’re not talking about the "file didn’t open" kind of error. Nope, we’re talking about "game over, stop everything, hit the eject button" failure. In .NET, you’re familiar with exceptions. In Rust, there’s something called panic!. But these two aren’t quite the same thing. Rust draws a hard line between recoverable errors and unrecoverable failures, and understanding that line is a big mindset shift for anyone coming from C#. - [Error Propagation with ?: So Simple, So Smart](https://woodruff.dev/error-propagation-with-so-simple-so-smart/) - Day 24... today we’re digging into one of my favorite "why doesn’t every language have this?" features in Rust: the ? operator. If you've spent any time in C#, you're no stranger to the good ol’ try/catch flow. You wrap some code in a try, you catch the exception, and you hope you didn’t forget to check for null or some unexpected state. Rust takes a different approach with Result and the magic of the ? operator. It keeps your error handling clean, readable, and safe without the overhead (or drama) of exceptions. - [Crates and Dependencies: NuGet, Meet Cargo](https://woodruff.dev/crates-and-dependencies-nuget-meet-cargo/) - Day 23... let’s talk about how Rust gets its packages! If you’re coming from the .NET world, you’re no stranger to NuGet. It’s been your trusty sidekick for pulling in libraries, managing versions, and bloating that csproj file with package references. In Rust, the equivalent is Cargo, and its packages are called crates. But here’s the twist: Cargo doesn’t just handle your dependencies. It’s your project manager, your build system, your tester, and your publisher, all rolled into one delightful tool. - [Organizing Code: Rust Modules vs C# Namespaces](https://woodruff.dev/organizing-code-rust-modules-vs-c-namespaces/) - Welcome to Day 22! After a week of wrestling with data modeling, it’s time to talk about something near and dear to every developer’s heart: keeping your code organized (and your sanity intact). If you're a C# developer, you've lived in the world of namespaces, public and internal access modifiers, and .cs files that can stack up faster than your coffee cups during crunch time. In Rust, the story is a little different, but delightfully simple once you get the hang of it. - [Week 3: Wrap-Up: Data Modeling That Fights Back](https://woodruff.dev/week-3-wrap-up-data-modeling-that-fights-back/) - Three weeks into Rust, and if your brain isn’t at least a little bit melted, I applaud your resilience! This week was all about data modeling. But not just any modeling—the kind that actively fights back when you try to make bad decisions. If you're used to the world of C#, you probably lean on classes, POCOs, and the occasional enum to represent state. And hey, that works… until it doesn’t. Rust’s structs and enums bring some serious muscle to the table by making sure your data models are clear, correct, and (most importantly) safe by design. Let’s take a moment to reflect on what we learned and why Rust’s approach makes data modeling feel less like a "best practices" hope-and-pray scenario and more like a language-enforced guarantee. - [Result: A Better Way to Fail](https://woodruff.dev/result-a-better-way-to-fail/) - Welcome to Day 20! Today we’re talking about failure, but in the best possible way. Because, let's be honest, things go wrong. Files go missing. Network calls timeout. Data isn’t always what we expect. And if you've been living in the .NET world like I have, your first instinct might be to reach for the trusty try-catch block. Rust, though? Rust says, "Let’s not wait until runtime to deal with failure. Let’s handle it right now, at compile time." And the tool that it gives us to do that is Result. Rust, though? Rust says, "Let’s not wait until runtime to deal with failure. Let’s handle it right now, at compile time." And the tool it gives us to do that is Result. - [Option: Where Null Is Not an Option](https://woodruff.dev/optiont-where-null-is-not-an-option/) - Ah, nulls, the "billion-dollar mistake" that haunts just about every C# developer. How many times have you chased down a NullReferenceException, muttering under your breath, "But how could this even be null?" Well, guess what? In Rust, nulls are not a thing. At least, not in the wild-and-dangerous sense we're used to in .NET. Instead, Rust gives us Option. And let me tell you, once you get a taste of it, you'll wonder why we ever let null run loose in the first place. - [Destructuring: Pattern Matching’s Power Move](https://woodruff.dev/destructuring-pattern-matchings-power-move/) - We’ve made it to Day 18, and today we’re going to unlock one of the coolest moves in Rust’s pattern matching toolkit: destructuring. If you've played around with C# 7+ deconstruction, you're already familiar with the idea of "pulling things apart" for easier access. But Rust? Rust takes that idea, cranks it up, and throws in some extra muscle. - [Match: Switch on Steroids](https://woodruff.dev/match-switch-on-steroids/) - Welcome to Day 17! By now, we've covered some seriously cool Rust features, but today might be my favorite so far: the match expression. If you're coming from a C# background—especially with the newer C# 8+ switch expressions—you might think you've seen it all. Trust me, Rust's match is like a switch statement on steroids, protein shakes, and a Red Bull chaser. - [Enums: Discriminated Unions Done Right](https://woodruff.dev/enums-discriminated-unions-done-right/) - Welcome to day 15! Today, we're diving into Rust's enums—and spoiler alert—they're not your typical enums from C#. Rust enums are powerful, flexible, and genuinely fun. If you've ever looked longingly at F#'s discriminated unions (or scratched your head at C#'s enums), you're about to discover something delightful. - [Rust Structs vs C# Classes: Less is More](https://woodruff.dev/rust-structs-vs-c-classes-less-is-more/) - Welcome back! After wrestling with Rust's strict ownership rules, let's ease into something a little more familiar (yet refreshingly different): structs. As a C# developer, you're probably thinking, "Oh, great, Rust structs are just classes, right?" Well, not exactly. Rust structs offer a minimalist and highly efficient way to structure data, contrasting nicely with our beloved C# Plain Old CLR Objects (POCOs). - [Week 2: Reflections on Ownership Week: My Brain Hurts (in a Good Way)](https://woodruff.dev/week-2-reflections-on-ownership-week-my-brain-hurts-in-a-good-way/) - It's official—week two of learning Rust has wrapped, and I've survived. Mostly. This week was all about ownership, borrowing, and wrestling with Rust's strict rules. And boy, did my C# brain get a workout! It hurts, but honestly, it's the good kind of pain—the one you feel after finally nailing that tough workout or solving an especially nasty bug. - [Shadowing in Rust: Redeclaring with Style](https://woodruff.dev/shadowing-in-rust-redeclaring-with-style/) - We've all been there. You're coding away, and suddenly you reuse a variable name without realizing it. If you're a C# developer, your brain probably triggers a warning alarm, screaming something like, "Hey, buddy! You've already used that name!" But guess what? In Rust, this isn't just allowed—it's encouraged, and it even has a cool name: shadowing. So what exactly is shadowing, and why does Rust promote it? Let's dive in and explore how this stylish redeclaration trick differs from what we're used to in C#. - [Slices and Strings with Rust: Goodbye C# StringBuilder?](https://woodruff.dev/slices-and-strings-goodbye-c-stringbuilder/) - When you’ve spent years writing C#, you get really comfortable with string being immutable, Span being your performance trick, and StringBuilder being your go-to hammer when a for loop starts building text. And then you start learning Rust. Suddenly, String isn’t immutable. &str looks suspiciously like a Span in disguise. And you realize… wait, do I even need a StringBuilder anymore? Today on Day 12, I dove into slices and strings in Rust, and let me tell you, it’s a whole new world, but a surprisingly elegant one. - [The Borrow Checker: Rust’s Tough-Love Mentor](https://woodruff.dev/the-borrow-checker-rusts-tough-love-mentor/) - You think you’ve been writing safe code… until you meet the Rust borrow checker. Then suddenly, your once-proud instincts are being side-eyed by a compiler that’s not mad, just disappointed. Today, on Day 11 of my Rust journey, we talk about the infamous, unyielding, sometimes infuriating, but ultimately brilliant guardian of Rust safety: the borrow checker. - [Borrowing and References: Rust’s Version of ref (But Nicer)](https://woodruff.dev/borrowing-and-references-rusts-version-of-ref-but-nicer/) - If you've been writing C# for a while, you’ve likely crossed paths with ref, in, and out parameters. They allow you to pass variables by reference, enabling a method to read or modify the original value. Useful? Definitely. Safe? Uh... sometimes. In Rust, there's a similar concept called borrowing. It uses & and &mut, and it feels a lot like passing ref or in in C#, but with one significant difference: The compiler enforces safety rules that make data races and invalid access impossible. Today, we’re diving into borrowing, references, and how Rust holds your hand (and your memory) without letting you write foot-gun code. - [Move Semantics in Rust: What Just Happened to My Variable?](https://woodruff.dev/move-semantics-in-rust-what-just-happened-to-my-variable/) - Okay, so picture this: you're cruising along in your nice, type-safe Rust code, and suddenly... your variable vanishes. Not literally, of course. But the compiler throws a fit, and you’re left staring at an error that says something like: "value borrowed here after move". Wait, move? Welcome to move semantics, Rust’s very opinionated way of managing memory and keeping you from accidentally using things that don’t belong to you anymore. Today’s post is a follow-up to yesterday’s crash course in ownership and this one might sting a little at first if you're coming from the comfy world of .NET’s reference types. But stick with me. It’s about to make sense. - [Ownership in Rust: The Most C++-ish Thing I’ve Loved (and I Mean That in a Good Way)](https://woodruff.dev/ownership-in-rust-the-most-c-ish-thing-ive-loved-and-i-mean-that-in-a-good-way/) - Let’s get one thing out of the way: as a C# developer, I’ve never had to think too hard about memory. The garbage collector (GC) is always there, lurking in the background, sweeping up after my code, like a very polite, very invisible butler. But Rust? Rust doesn’t do garbage collection. There’s no GC.Collect(), no memory profiler needed to chase leaks from forgotten Dispose() calls. Instead, Rust gives you something bold, powerful, and… at first, kind of intimidating: Ownership. Today’s post kicks off Week 2 of my Rust adventure, and it’s all about how this one idea changes everything. - [Reflections on Week 1: Rust's Minimalism Hits Different](https://woodruff.dev/reflections-on-week-1-rusts-minimalism-hits-different/) - Seven days into learning Rust, and I feel like I’ve been through a developer bootcamp with a compiler that doubles as a personal trainer. It doesn’t let you slack, but it does make you better. This week, I went from installing the toolchain to wrestling with immutable variables and puzzling over semicolons in return statements. As a C# developer, I expected syntax differences, but I didn’t expect the philosophical shifts. Let’s recap what stood out, what stung, and why I’m still excited to keep going. - [Functions in Rust: Familiar Yet Different](https://woodruff.dev/functions-in-rust-familiar-yet-different/) - Today’s Rust lesson hit a familiar note but with a twist. Writing functions in Rust feels almost like writing them in C#. Until, of course, the compiler reminds you that this language doesn’t always play by the same rules. On Day 5 of my Rust-for-C# developers journey, let’s break down function definitions, type inference, return values, and where Rust and C# shake hands... and where they give each other a suspicious side-eye. On Day 5 of my Rust-for-C# developers journey, let’s break down function definitions, type inference, return values, and where Rust and C# shake hands... and where they give each other a suspicious side-eye. - [Variables in Rust: Let Me Be Immutable](https://woodruff.dev/variables-in-rust-let-me-be-immutable/) - So today, I ran head-first into a Rust design decision that made me pause and go, “Wait… really?” In C#, I can declare a variable with var and change it later. No fuss. In Rust? Not so fast. Your variables are frozen solid if you don’t explicitly ask for mutability. Welcome to Day 4: the world of let, mut, and what happens when your muscle memory meets a strict compiler. - [Hello, Rust! Hello, World! Rust vs C# Syntax](https://woodruff.dev/hello-rust-hello-world-rust-vs-c-syntax/) - Let’s be honest—every new language journey begins the same way: with a humble "Hello, World!" It’s the developer's rite of passage. So today, on Day 3 of my 42-day Rust challenge, I’m writing the most iconic two-word phrase in programming in both C# and Rust… and then tearing it apart. Because while the output is the same, what these two languages make you say to get there reveals a lot about how they think. - [dotnet new, Meet cargo new: A Tale of Two CLIs](https://woodruff.dev/dotnet-new-meet-cargo-new-a-tale-of-two-clis/) - It’s Day 2 of my journey learning Rust as a longtime C# developer, and today I took the plunge: I installed Rust and created my first project. The whole thing felt a bit like unpacking a new toolbox—familiar enough to recognize the tools, but different enough that I had to check the manual. - [Why Rust? A C# Developer’s Journey Begins](https://woodruff.dev/why-rust-a-c-developers-journey-begins/) - Today marks Day 1 of my 42-day challenge to learn Rust—with a twist. I’m not approaching this as a blank-slate beginner. I’m bringing along years of C# experience, mental muscle memory from countless LINQ expressions, async/await workflows, and enough IEnumerables to make your head spin. But now? I’m learning a language that doesn’t have a garbage collector, doesn’t throw exceptions the same way, and thinks null is a bad idea. - [Swapping and Targeting Like a Pro: htmx Magic for Razor Pages](https://woodruff.dev/swapping-and-targeting-like-a-pro-htmx-magic-for-razor-pages/) - Welcome back, htmx explorer. Today, we’re unlocking two of the most powerful tools in the HTMX toolbox: hx-target and hx-swap. These are the keys to making your Razor Pages do exactly what you want without breaking a sweat. - [Rust for the Sharp Mind: 6 Weeks of Learning Rust as a C# Developer](https://woodruff.dev/rust-for-the-sharp-mind-6-weeks-of-learning-rust-as-a-c-developer/) - What will happen when you take a C# developer, hand them a curly-brace language that loves safety and hates nulls, and give them six weeks to figure it out? You will experience a journey filled with rewired brain circuits, redefined mental models, and a newfound respect for the compiler. This will mark the beginning of my 42-day dive into Rust, a daily learning challenge that will push me out of my .NET comfort zone and into a language that promises to be both frustratingly strict and beautifully empowering. - [The Future of Server-Driven Web Apps: Why htmx and ASP.NET Are Just Getting Started](https://woodruff.dev/the-future-of-server-driven-web-apps-why-htmx-and-asp-net-are-just-getting-started/) - Welcome back, Razor Pages fan. Today, we’re looking ahead at where htmx and ASP.NET Core are heading in the grand scheme of web development. Spoiler alert: Server-driven apps are making a comeback, and htmx is leading the charge. - [Keeping Your htmx Apps Safe: Security Best Practices for ASP.NET Developers](https://woodruff.dev/keeping-your-htmx-apps-safe-security-best-practices-for-asp-net-developers/) - Alright, developer friends, it’s time to talk about something we all know is essential but often neglect until it’s too late: security. htmx makes building interactive apps with ASP.NET Razor Pages a breeze, but if you’re not careful, you could be opening your app to all sorts of nasty vulnerabilities. Let’s make sure that doesn’t happen. - [Debugging htmx in ASP.NET Razor Pages: Tips, Tricks, and Tools](https://woodruff.dev/debugging-htmx-in-asp-net-razor-pages-tips-tricks-and-tools/) - Welcome back, fellow developer! So you’ve embraced htmx to make your ASP.NET Razor Pages more interactive and excellent. But just like anything in development, things can go wrong. And when they do, you need to know how to fix them. Today, we’re diving into debugging HTMX requests and responses like a pro. - [Boosting Razor Pages UX: The htmx Upgrade You Need](https://woodruff.dev/boosting-razor-pages-ux-the-htmx-upgrade-you-need/) - Hey there, fellow .NET developer! Today, we’re talking about how you can take your ASP.NET Razor Pages apps from "meh" to "whoa!" with htmx. We’re diving into seamless navigation, enhancing user interactions, and even doing a little case study to show you how this all comes together. Ready? Let’s go. - [htmx vs. JavaScript Frameworks: Choosing the Right Tool for the Job](https://woodruff.dev/htmx-vs-javascript-frameworks-choosing-the-right-tool-for-the-job/) - Alright, web developers. Today, we’re stepping into the ring to watch htmx go toe-to-toe with the big players: React, Vue, and Angular. But this isn’t a deathmatch. It’s about finding the right tool for the right job. Let’s get into it. - [htmx for ASP.NET Core Developers: The Simpler, Faster Way to Build Web Apps](https://woodruff.dev/htmx-for-asp-net-core-developers-the-simpler-faster-way-to-build-web-apps/) - Welcome back, fellow .NET enthusiast. Today, we’re talking about why htmx is a game-changer for ASP.NET Core developers. If you’re tired of drowning in client-side frameworks and you want something simpler without sacrificing performance, you’re in the right place. - [Going Modular: Using htmx with Partial Views in Razor Pages](https://woodruff.dev/going-modular-using-htmx-with-partial-views-in-razor-pages/) - Hey there, fellow coder. Today, we’re diving into the wonderful world of partial views and how you can make them dance beautifully with htmx. If you’ve ever wanted to break down your Razor Pages into reusable, modular components, you’re going to love this. Let’s get rolling. - [CRUD Made Easy: Building Dynamic Apps with htmx and ASP.NET Razor Pages](https://woodruff.dev/crud-made-easy-building-dynamic-apps-with-htmx-and-asp-net-razor-pages/) - Welcome back, developer! Today, we’re tackling something everyone needs to build at some point: a CRUD (Create, Read, Update, Delete) application. And guess what? We’re going to do it without the JavaScript bloat. That’s right, htmx is here to make your CRUD dreams come true. - [Real-Time Magic: Live Updates with htmx and ASP.NET Razor Pages](https://woodruff.dev/real-time-magic-live-updates-with-htmx-and-asp-net-razor-pages/) - Welcome back, code adventurer. Today, we’re diving into how htmx can give your ASP.NET Razor Pages some real-time flavor. Whether you want to build a chat app, a live stock ticker, or a dashboard that updates itself without manual refreshing, htmx has you covered. - [Interactive Forms Made Easy: htmx Meets ASP.NET Razor Pages](https://woodruff.dev/interactive-forms-made-easy-htmx-meets-asp-net-razor-pages/) - Welcome back to the HTMX party! Today, we’re talking about a topic every web developer has wrestled with at some point: forms. They’re essential, but making them play nicely with your backend can sometimes feel like wrestling a bear. Enter HTMX. It’s here to simplify your form handling and make the experience feel smooth and modern. - [Mastering htmx Attributes: Your Toolkit for Razor Pages Awesomeness](https://woodruff.dev/mastering-htmx-attributes-your-toolkit-for-razor-pages-awesomeness/) - Welcome back, coders! Now that you’ve dipped your toes into the htmx waters, it’s time to wade in a little deeper. Today, we’re diving headfirst into htmx attributes — the secret sauce that makes your Razor Pages dance with interactivity. So, buckle up and get ready for some fun! - [htmx + ASP.NET Razor Pages: Your First Dance with Interactivity](https://woodruff.dev/htmx-asp-net-razor-pages-your-first-dance-with-interactivity/) - Hey there, fellow C# wizard! Ready to sprinkle some HTMX magic on your ASP.NET Razor Pages? You’re about to see how easy it is to get started with HTMX and add dynamic features without turning your app into a JavaScript spaghetti mess. Let’s boogie! - [Level Up Your Razor Pages: Meet htmx, Your New Best Friend](https://woodruff.dev/level-up-your-razor-pages-meet-htmx-your-new-best-friend/) - Hey there, fellow ASP.NET developer! If you’re tired of wrestling with JavaScript frameworks or want to simplify your life, you’re in for a treat. Today, we’re diving into the wonderful world of HTMX and why it might just be the missing piece to make your ASP.NET Razor Pages even more awesome. - [Back to the Past: How htmx is Reviving Server-Driven Web Development](https://woodruff.dev/back-to-the-past-how-htmx-is-reviving-server-driven-web-development/) - Hey folks! Welcome back to the HTMX journey. Today, we’re diving into a bit of web development history and how HTMX is taking us forward... by looking backward. Cue the DeLorean, because we’re heading back to the days when server-driven development was all the rage. - [REST Constraint #6: Code on Demand—When, Why, and How to Use It](https://woodruff.dev/rest-constraint-6-code-on-demand-when-why-and-how-to-use-it/) - Of all the REST constraints, Code on Demand is the one that most developers either overlook or actively avoid. Unlike the other five constraints, it is the only optional one, meaning a RESTful system doesn’t have to use it. But when applied correctly, it can unlock powerful capabilities in web applications. Let’s explore what Code on Demand is, when it makes sense to use it, and why most REST APIs don’t rely on it. - [REST Constraint #5: Embracing Layers for Flexibility and Scale](https://woodruff.dev/rest-constraint-5-embracing-layers-for-flexibility-and-scale/) - Building a reliable, scalable web application is no easy feat. The internet is unpredictable, traffic surges happen, and security threats lurk around every corner. That’s why REST includes the Layered System constraint—a design principle that structures applications into multiple layers, each handling a specific role. Whether it’s distributing traffic, securing data, or managing services, layering helps RESTful systems stay resilient and adaptable. - [REST Constraint #4: Cacheable for Better Performance](https://woodruff.dev/rest-constraint-4-cacheable-for-better-performance/) - The internet is fast—until it’s not. Nobody likes waiting for a sluggish API response, and overloaded servers don’t help either. That’s where caching comes in. RESTful APIs embrace caching to improve performance, reduce server load, and create a smoother user experience. But caching isn’t just about speed—it’s about efficiency. Let’s dive into how REST makes caching an essential part of scalable web applications. - [REST Constraint #3: Going Stateless for Scalability](https://woodruff.dev/rest-constraint-3-going-stateless-for-scalability/) - When it comes to building scalable web applications, statelessness is one of REST’s most powerful constraints. It simplifies architecture, makes scaling easier, and helps APIs handle massive traffic loads without breaking a sweat. But what does being “stateless” actually mean in REST, and why is it such a big deal? - [REST Constraint #2: Why Client-Server Separation is a Game Changer](https://woodruff.dev/rest-constraint-2-why-client-server-separation-is-a-game-changer/) - The internet as we know it thrives on separation—specifically, the separation of clients and servers. It’s a fundamental principle of REST and a key factor in building scalable, maintainable, and flexible applications. But what exactly does this separation mean, and why does it matter? Let’s dive into the Client-Server constraint, one of REST’s six core architectural principles. - [REST Constraint #1: The Power of a Uniform Interface](https://woodruff.dev/rest-constraint-1-the-power-of-a-uniform-interface/) - A well-designed REST API isn’t just a random collection of endpoints—it follows a set of principles that make it predictable, scalable, and easy to use. One of the core constraints of REST is the Uniform Interface. This principle ensures that APIs are structured consistently, reducing complexity for both developers and systems interacting with them. - [RESTful API Design: Why Simplicity Wins](https://woodruff.dev/restful-api-design-why-simplicity-wins/) - APIs are the backbone of modern applications, and getting their design right can mean the difference between an easy-to-use system and a frustrating mess. That’s where REST (Representational State Transfer) comes in. RESTful API design focuses on simplicity, scalability, and a resource-oriented approach that makes APIs intuitive and robust. Let’s explain why REST improves API design and helps developers build better systems. - [The REST Formula: Six Principles That Keep the Web Running Smoothly](https://woodruff.dev/the-rest-formula-six-principles-that-keep-the-web-running-smoothly/) - REST isn’t just a set of suggestions—it’s built on a strict set of architectural principles that make it scalable, flexible, and resilient. These six constraints define what makes an API truly RESTful and ensure it can handle anything from simple web apps to large-scale distributed systems. Let’s break them down and see why they matter. - [REST: From Dissertation to Dominating the Web](https://woodruff.dev/rest-from-dissertation-to-dominating-the-web/) - The internet runs on a lot of things—electricity, servers, cat videos—but when it comes to how web applications communicate, REST has been leading the way for over two decades. But where did REST come from? And how did it go from an academic concept to powering the world’s most significant web services? Let’s dive into the origin and evolution of REST. - [REST Explained: Why the Web Runs on This Simple Idea](https://woodruff.dev/rest-explained-why-the-web-runs-on-this-simple-idea/) - If you've worked with web services, you've probably heard of REST. It's everywhere—from APIs powering your favorite apps to backend systems handling millions of users. But what exactly is REST, and why is it the go-to approach for modern web development? Let’s break it down. - [Decoding HTTP Response Codes: What Your Browser Isn’t Telling You](https://woodruff.dev/decoding-http-response-codes-what-your-browser-isnt-telling-you/) - Every time you visit a website, your browser and the server have a little chat. Sometimes, that conversation goes smoothly; sometimes, there’s a misunderstanding, and sometimes, everything falls apart. HTTP response codes communicate success, confusion, or complete failure. If you’ve ever seen a dreaded 404 Not Found or a mysterious 500 Internal Server Error, you’ve already encountered them. But what do these numbers actually mean, and why should you care? Let’s break it down. - [Breaking Down HTTP: What Really Happens in a Request and Response](https://woodruff.dev/breaking-down-http-what-really-happens-in-a-request-and-response/) - When you visit a website, stream a video, or send a form, your browser and a server are having a conversation. But what are they actually saying? Every interaction on the web boils down to HTTP requests and responses, which work together like a question-and-answer session between your browser (the client) and the server. Let's break them down. - [HTTP Methods: The Verbs That Make the Web Go Round](https://woodruff.dev/http-methods-the-verbs-that-make-the-web-go-round/) - If HTTP were a language, its methods—also known as verbs—would be the action words that keep the internet running. Every time you load a webpage, submit a form, or delete a post, you're using one of these methods. Understanding them is key to working with web APIs, debugging issues, and just generally feeling like a web wizard. Let’s break them down. - [HTTP Demystified: The Secret Sauce of the Web](https://woodruff.dev/http-demystified-the-secret-sauce-of-the-web/) - The internet—our beloved realm of cat videos, memes, and, occasionally, productivity—wouldn’t be the same without HTTP. It’s the invisible magic behind every website you visit. But what exactly is it, and how does it work? Buckle up because we’re about to take a joyride through the world of HTTP! - [Disaster-Proof Your Cloud: Automating Recovery with Terraform](https://woodruff.dev/disaster-proof-your-cloud-automating-recovery-with-terraform/) - Picture this: Your production system crashes at 2 AM. Servers are down. Databases are unreachable. Your inbox is exploding with alerts. Panic mode activated. That’s the power of Automated Disaster Recovery with Terraform. - [Terraform Evolution: Growing Your Infrastructure Without the Chaos](https://woodruff.dev/terraform-evolution-growing-your-infrastructure-without-the-chaos/) - Terraform is amazing for spinning up infrastructure fast, but what happens when your small project grows into a full-blown production system? - [Terraform in Action: Real-World Success Stories from the Cloud](https://woodruff.dev/terraform-in-action-real-world-success-stories-from-the-cloud/) - Terraform isn’t just a cool tool for spinning up infrastructure—it’s transforming how companies build, scale, and secure their cloud environments. But how does Terraform actually help real companies? In this post, we’ll explore real-world case studies where Terraform helped businesses: Automate infrastructure deployments and save time. Reduce cloud costs by optimizing resources. Scale seamlessly across - [Terraform Power-Ups: The Best Tools to Supercharge Your IaC Workflow](https://woodruff.dev/terraform-power-ups-the-best-tools-to-supercharge-your-iac-workflow/) - Terraform is already an amazing tool for automating infrastructure, but what if I told you it could get even better? Yes, Terraform has an entire ecosystem of tools that: Improve collaboration (no more breaking each other’s state files!). Automate approvals and deployments (less clicking, more coding!). Enhance security and compliance (because nobody wants a misconfigured - [Terraform + Monitoring: Keeping an Eye on Your Infrastructure 24/7](https://woodruff.dev/terraform-monitoring-keeping-an-eye-on-your-infrastructure-24-7/) - You’ve built your cloud infrastructure with Terraform—awesome! But now what? How do you know if your VMs are running smoothly? What if your databases are overloading or your Kubernetes cluster is on fire? Infrastructure isn’t set it and forget it—you need real-time monitoring to catch issues before users notice. Good news: Terraform can deploy and configure monitoring tools so you can track metrics, set up alerts, and visualize performance effortlessly! - [Terraform Testing: Catching Bugs Before They Break Your Cloud](https://woodruff.dev/terraform-testing-catching-bugs-before-they-break-your-cloud/) - You wouldn’t deploy code without testing it, right? So why would you push infrastructure changes without making sure they work? Terraform makes it easy to define infrastructure, but one wrong line of code can delete everything. That’s why testing Terraform configurations is essential—to catch issues before they reach production. - [Terraform on Autopilot: Building Dynamic, Self-Scaling Infrastructure](https://woodruff.dev/terraform-on-autopilot-building-dynamic-self-scaling-infrastructure/) - What if your infrastructure could scale itself up when traffic spikes and shrink when demand drops? What if it could self-heal when things break—without you lifting a finger? Sounds futuristic? It’s possible today with Terraform! With dynamic infrastructure, Terraform can: Auto-scale compute resources based on demand. Adjust networking and storage dynamically. Trigger infrastructure changes using event-driven automation. - [Mastering Multi-Cloud: Deploying Across AWS, Azure, and GCP with Terraform](https://woodruff.dev/mastering-multi-cloud-deploying-across-aws-azure-and-gcp-with-terraform/) - Imagine this: Your company just merged with another, and suddenly, you're managing infrastructure across AWS, Azure, and Google Cloud. Or maybe your team wants multi-cloud resilience—so if one provider has an outage, your apps keep running elsewhere. Smart move! But managing multiple clouds manually? That’s a nightmare. Fortunately, Terraform makes multi-cloud deployments easy, repeatable, and scalable. - [From Chaos to Code: Migrating Legacy Infrastructure to Terraform](https://woodruff.dev/from-chaos-to-code-migrating-legacy-infrastructure-to-terraform/) - Raise your hand if you’ve ever inherited a mess of manually created cloud resources. Maybe your team has been clicking around in cloud consoles for years, and now your infrastructure is an unmanageable, undocumented monster. Or perhaps you have hundreds of resources, and nobody knows exactly how they were configured. Sound familiar? Don’t worry—Terraform can bring order to the madness! - [Terraform Troubleshooting: Fixing Fails, Errors, and Cloud Chaos](https://woodruff.dev/terraform-troubleshooting-fixing-fails-errors-and-cloud-chaos/) - Terraform is amazing—until it isn’t. One moment, you're deploying infrastructure effortlessly, and the next, you're staring at an error message that makes no sense. We’ve all been there. Whether it’s state file conflicts, provider issues, or mysterious dependency errors, Terraform troubleshooting can be frustrating—but it doesn’t have to be! - [Cut Cloud Costs with Terraform: Automate, Optimize, and Save Money](https://woodruff.dev/cut-cloud-costs-with-terraform-automate-optimize-and-save-money/) - Cloud bills piling up faster than you expected? Terraform isn't just for deploying infrastructure—it’s also an awesome cost optimization tool! Instead of manually tracking expenses and hoping for the best, Terraform helps you: Monitor and control cloud costs before they spiral out of control. Automate cost-efficient resource provisioning (no more oversized VMs!). Enforce budget limits and alerts so there are no nasty surprises. - [Terraform + Azure DevOps: Automate Your Cloud Deployments the Smart Way](https://woodruff.dev/terraform-azure-devops-automate-your-cloud-deployments-the-smart-way/) - Manually deploying infrastructure is so last decade. If you’re still running terraform apply on your local machine, it’s time to step up your game with Azure DevOps Pipelines! - [Lock It Down: Security Ideas for Terraform Deployments](https://woodruff.dev/lock-it-down-security-ideas-for-terraform-deployments/) - Terraform makes infrastructure automation easy, but if you’re not careful, it can also open the door to security risks—misconfigured permissions, exposed secrets, and unintended data leaks. Let’s talk about how to secure your Terraform deployments so you don’t end up as the next cloud security horror story. - [Terraform Good Practices: Avoiding Chaos and Building with Confidence](https://woodruff.dev/terraform-good-practices-avoiding-chaos-and-building-with-confidence/) - Terraform is an amazing tool for managing infrastructure, but without best practices, things can get messy—fast. Imagine a world where: Terraform state files vanish into thin air. Untracked changes wreck your deployments. Infrastructure drifts into an unknown state. Sounds like a nightmare, right? - [Terraform in the Wild: Real-World Use Cases That Make Cloud Magic Happen](https://woodruff.dev/terraform-in-the-wild-real-world-use-cases-that-make-cloud-magic-happen/) - Terraform isn't just a fancy tool for spinning up VMs—it’s the backbone of modern cloud automation. Whether you're managing multi-cloud environments, automating disaster recovery, or deploying Kubernetes clusters, Terraform has got you covered. In this post, we’ll dive into practical use cases where Terraform truly shines, proving that Infrastructure as Code (IaC) isn’t just a buzzword—it’s a game-changer. - [Terraform Power Moves: Unlocking Advanced Features for Smarter Infrastructure](https://woodruff.dev/terraform-power-moves-unlocking-advanced-features-for-smarter-infrastructure/) - So, you’ve mastered Terraform basics, spun up some resources, and maybe even dabbled with modules. But what if I told you Terraform can do even more? In this post, we’re going to explore Advanced Terraform Features that will make your infrastructure smarter, more dynamic, and easier to manage. - [Terraform Modules: Stop Copy-Pasting and Start Reusing Like a Pro](https://woodruff.dev/terraform-modules-stop-copy-pasting-and-start-reusing-like-a-pro/) - Ever feel like you’re copy-pasting the same Terraform code over and over again? Deploying resource groups, VMs, networks—all with slightly different names? Yeah, that’s a nightmare waiting to happen. Luckily, Terraform modules exist to make our lives easier! Modules let you write infrastructure code once and reuse it across different projects, environments, or even teams. - [Kill the Bloat: The Controversial Clash Between SPAs, Server-Side Rendering, and the Power of Simplicity](https://woodruff.dev/kill-the-bloat-the-controversial-clash-between-spas-server-side-rendering-and-the-power-of-simplicity/) - Ever feel like half your development time goes to chasing down strange bugs in a colossal JavaScript stack that only a wizard could appreciate? You’re not alone. In the realm of web apps, we’re always trying to determine whether it’s better to handle everything on the server or shift as much as possible to the browser. This discussion isn’t just about technology—it’s about maintaining manageable code, keeping our sanity intact, and ensuring our users are happy. Enter the Simplicity-First philosophy, which reminds us that while fancy frameworks and cutting-edge libraries are appealing, they become useless if they overwhelm our code with excessive complexity. Simplicity-First is the sidekick that shows up with a utility belt full of best practices: naming things well, writing readable functions, and structuring elements so that future you (or your teammates) don’t have to pull out their hair. Buckle up as we embark on a journey through the history of server-side vs. client-side, explore why understanding your domain is crucial, and discover how new tools like htmx or server-first frameworks might bring peace to the galaxy. - [Terraform Variables & Outputs: The Secret Sauce of Reusable Infrastructure](https://woodruff.dev/terraform-variables-outputs-the-secret-sauce-of-reusable-infrastructure/) - If you've ever hardcoded values in Terraform, I have some bad news… and some great news! The bad news? Hardcoding is a one-way ticket to frustration and messy code. The great news? Terraform variables and outputs can save your sanity by making your infrastructure code dynamic, reusable, and scalable. - [Terraform Workflow: Plan It, Build It, Rule the Cloud](https://woodruff.dev/terraform-workflow-plan-it-build-it-rule-the-cloud/) - If you’ve ever tried assembling IKEA furniture without looking at the instructions (we’ve all been there), you know how chaotic it can get. Terraform is no different—if you don’t follow the right workflow, you’ll end up with a cloud mess instead of a well-structured infrastructure. Thankfully, Terraform has a straightforward workflow that helps you move from defining your infrastructure to deploying it seamlessly. In this post, we’ll break down the key steps of the Terraform workflow and how to use them like a pro! - [The State of Terraform: Keeping Your Cloud Empire in Check](https://woodruff.dev/the-state-of-terraform-keeping-your-cloud-empire-in-check/) - Managing infrastructure can feel like herding cats—if you don’t keep track of what’s going on, chaos ensues. That’s where Terraform state comes in. It’s like the master ledger for your cloud empire, tracking every resource Terraform manages so you don’t lose your mind. - [Speaking Terraform: A Crash Course in HCL](https://woodruff.dev/speaking-terraform-a-crash-course-in-hcl/) - Learning a new tool is like learning a new language—you’ve got to understand the grammar before you can start forming sentences. Terraform’s native tongue is HCL (HashiCorp Configuration Language), and trust me, it’s way easier than high school French (no weird verb conjugations here). In this post, we’ll break down the basics of HCL so you can write Terraform configurations that are clean, dynamic, and downright fun. - [Terraform 101: Your First Steps into Infrastructure as Code](https://woodruff.dev/terraform-101-your-first-steps-into-infrastructure-as-code/) - So, you’ve heard about Terraform, but you’re wondering: "What the heck is Terraform, and why should I use it?" - [Temporal Tables in EF Core: Bringing Time Travel to Your Data](https://woodruff.dev/temporal-tables-in-ef-core-bringing-time-travel-to-your-data/) - What if you could go back in time and see exactly what your database looked like yesterday, last week, or even last year? Sounds like something out of a sci-fi movie, right? Well, Temporal Tables in SQL Server let you do exactly that! - [JSON Columns in SQL Server: Storing & Querying JSON with EF Core](https://woodruff.dev/json-columns-in-sql-server-storing-querying-json-with-ef-core/) - Ever wished you could store semi-structured data in your database without dealing with complex table relationships? Good news! SQL Server has native JSON support, and EF Core makes working with JSON columns easier than ever. Whether you’re handling dynamic configurations, logging data, or flexible user preferences, JSON columns let you mix structured and unstructured data in SQL Server—without creating dozens of extra tables. - [Keyless Entity Types in EF Core: Query Data Without Primary Keys](https://woodruff.dev/keyless-entity-types-in-ef-core-query-data-without-primary-keys/) - Not everything in your database needs a primary key. Sometimes, you just want to query views, stored procedures, or raw SQL results without forcing a unique identifier on them. That’s where Keyless Entity Types in EF Core come in! If you’ve ever struggled with querying database views, reports, or read-only datasets, this feature is exactly what you need. Let’s dive into what Keyless Entity Types are, when to use them, and how to make them work in EF Core. - [Grouping Smarter: LINQ GroupBy Enhancements in EF Core](https://woodruff.dev/grouping-smarter-linq-groupby-enhancements-in-ef-core/) - Grouping data in Entity Framework Core (EF Core) used to feel a little… clunky. Sometimes, LINQ’s GroupBy() worked beautifully in-memory but got lost in translation when executing SQL queries. You’d write a simple GroupBy(), and EF Core would pull all the data into memory before doing the grouping—not good! But things are getting smarter and more efficient in recent versions of EF Core! With LINQ GroupBy enhancements, EF Core now translates more grouping operations into optimized SQL queries, saving memory and improving performance. - [Transactional Savepoints in EF Core: Rollback Just What You Need!](https://woodruff.dev/transactional-savepoints-in-ef-core-rollback-just-what-you-need/) - We’ve all been there—you’re halfway through a multi-step transaction, and boom! 💥 Something fails. You don’t want to roll back everything, just the part that went wrong. That’s where Transactional Savepoints come in! Savepoints let you partially roll back transactions, keeping the good stuff while undoing just the problematic parts. If you've ever wished for a "Ctrl + Z" in database operations, this is it. - [Tapping into Database Views with EF Core: Reverse Engineering Made Easy](https://woodruff.dev/tapping-into-database-views-with-ef-core-reverse-engineering-made-easy/) - Not all database tables are created equal! Sometimes, you don’t need direct access to raw data—you need a refined, read-only version that makes querying easier. That’s where database views come in! - [Mapping the World with EF Core: Working with Spatial Data](https://woodruff.dev/mapping-the-world-with-ef-core-working-with-spatial-data/) - Have you ever needed to store coordinates, track locations, or perform distance calculations in your database? Whether you're building a ride-sharing app, a location-based service, or an interactive map, working with spatial data is essential. Luckily, EF Core supports spatial data types, allowing you to store, query, and manipulate geographic data seamlessly. No more treating latitude and longitude as simple numbers—let’s bring real GIS (Geographic Information System) power to your EF Core apps! - [Global Query Filters: Setting the Rules Once, Querying Like a Pro](https://woodruff.dev/global-query-filters-setting-the-rules-once-querying-like-a-pro/) - Imagine you’re running a café. Every customer who walks in gets a free cookie—no need to ask for it, no need for your staff to remember. It just happens, automatically. That’s the magic of Global Query Filters in EF Core. Once you set them up, every query automatically follows the rules, making your code simpler and your life easier. Global Query Filters are all about efficiency and consistency. Let’s dive into how they work, why they’re awesome, and how to sprinkle them into your EF Core projects like those cookies at your café. - [Unlocking EF Core Performance: How to Track Queries with Event Counters](https://woodruff.dev/unlocking-ef-core-performance-how-to-track-queries-with-event-counters/) - If you've ever wondered why your EF Core queries feel sluggish or why your database is working overtime, you're not alone. Performance issues can creep in quietly, and before you know it, your app is struggling to keep up. Wouldn’t it be great if EF Core had built-in performance tracking so you could monitor database activity in real time? Good news—it does! - [Cracking the Code: Decoding Query Plans Like a Pro](https://woodruff.dev/cracking-the-code-decoding-query-plans-like-a-pro/) - like at first glance—cryptic, overwhelming, and maybe a little intimidating. But don’t worry! Once you embark on the journey to analyze and understand query plans, you’ll be unlocking hidden performance treasures like a true database pirate, and you'll be amazed at how much you can grow and learn in the process. - [Tracking Every Change: Using SaveChanges Interception for EF Core Auditing](https://woodruff.dev/tracking-every-change-using-savechanges-interception-for-ef-core-auditing/) - Ever wonder who changed what and when in your database? Or maybe you’ve had that “uh-oh” moment where data was updated, but no one knows how? Good news: EF Core has a built-in way to track changes—without modifying every query manually! SaveChanges Interception lets you hook into EF Core’s SaveChanges() pipeline and log inserts, updates, and deletes automatically. - [Many-to-Many Made Easy: Mastering Relationships in EF Core](https://woodruff.dev/many-to-many-made-easy-mastering-relationships-in-ef-core/) - Remember when dealing with many-to-many relationships in Entity Framework felt like trying to assemble IKEA furniture without instructions? You needed an extra join entity and sometimes a sprinkle of luck to get it all working. EF Core has come to the rescue, making many-to-many relationships as easy as pie (or a fully assembled bookshelf) and giving you improved configurations that put you in the driver's seat. - [Accelerating EF Core with Compiled Queries](https://woodruff.dev/accelerating-ef-core-with-compiled-queries/) - One of my passions is data! I love all forms of data and how to work with it. I am a .NET fanatic also and have been a fan of Entity Framework since 2008. It has gotten so good since .NET Core 1.0, and I love to push EF Core to the limit, especially around Web APIs. In this blog post, I want to share my ideas about Compiled Queries in EF Core. - [Batching Like a Boss: Using IDbContextFactory for High-Performance EF Core Updates](https://woodruff.dev/batching-like-a-boss-using-idbcontextfactory-for-high-performance-ef-core-updates/) - I love receiving feedback on my blog posts! After sharing "Batching Updates and Inserts: Making EF Core Work Smarter, Not Harder," I received some great comments, especially from MaxiTB on Mastodon, which I wanted to share. Batch operations—whether inserting or updating multiple records—can quickly lead to performance issues, particularly when DbContext is misused. However, with - [Query Tags: Debugging EF Core Like a Detective](https://woodruff.dev/query-tags-debugging-ef-core-like-a-detective/) - Imagine you’re a detective working on a big case. You’ve got a pile of clues (queries), but they’re all mixed together with no labels. Which one belongs to which part of the case? Frustrating, right? That’s what debugging EF Core queries feels like without Query Tags. But with Query Tags, it's like a breath of fresh air, relieving the frustration and making the process more manageable. Query Tags in EF Core are like sticky notes for your SQL. They allow you to label your queries, making it significantly easier to track down problems, optimize performance, and appear as a debugging wizard. - [Batching Updates and Inserts: Making EF Core Work Smarter, Not Harder](https://woodruff.dev/batching-updates-and-inserts-making-ef-core-work-smarter-not-harder/) - Let’s face it: making multiple database calls is like running back and forth between the kitchen and dining room to serve dinner one plate at a time. It’s inefficient, exhausting, and makes your app look like it’s stuck in the Stone Age. But with batching in EF Core, you can wave goodbye to this inefficiency. It's the magic trick that lets you update or insert multiple records in a single trip to the database, making you and your app more productive and efficient. Batching is all about doing more with less. It minimizes round trips to the database, saves resources, and makes your app faster. Understanding and implementing batching in EF Core is like gaining a superpower-it makes your app work smarter, not harder, and gives you a sense of control and confidence in your development process. - [No-Tracking Queries: Speed Up Your EF Core Like a Pro](https://woodruff.dev/no-tracking-queries-speed-up-your-ef-core-like-a-pro/) - Imagine you’re at a library, flipping through books at lightning speed. You don’t need to write notes in the margins or keep tabs on which books you’ve touched—you’re just reading. That’s what no-tracking queries are in EF Core: a way to grab data without keeping track of changes. It’s fast, lightweight, and perfect for read-only operations. But wait, there’s more! Let’s throw identity resolution into the mix, a smart way to avoid duplicate entities when working with no-tracking queries. Together, they make a dynamic duo for blazing-fast data fetching, significantly reducing the time it takes to retrieve data from the database. - [Query Projection: Stop Hauling More Data Than You Need!](https://woodruff.dev/query-projection-stop-hauling-more-data-than-you-need/) - Imagine you’re moving to a new house. You could pack only the essentials and enjoy a stress-free move, or you could drag everything you own—grandma’s old lamp, that broken treadmill, and a box labeled “random cables.” This analogy of moving to query projection makes the concept familiar and relevant. Moving with all that clutter? Nightmare. The same applies to your EF Core queries. Why fetch every column in a table when all you need is a handful of them? That’s where query projection comes in. It’s all about keeping your data lean, clean, and most importantly, efficient. Embracing query projection is like optimizing your coding practices for maximum efficiency. - [Explicit Includes: The Art of Fetching Just Enough Data in EF Core](https://woodruff.dev/explicit-includes-the-art-of-fetching-just-enough-data-in-ef-core/) - If you’ve ever gone grocery shopping while hungry, you know how easy it is to end up with more than you need. The same thing happens in EF Core when you’re too eager with your Include statements—you fetch all the data, even the stuff you don’t need, and suddenly, your app feels sluggish. That’s where Explicit Includes comes in, allowing you to fetch only what you need when needed, making your development process more efficient. Think of it as grocery shopping with a list, but for your code. - [Split Queries: Stop the Data Traffic Jam in EF Core](https://woodruff.dev/split-queries-stop-the-data-traffic-jam-in-ef-core/) - Picture this: You’re hosting a dinner party, and instead of serving everyone a delicious buffet, you deliver each dish one at a time to every guest. When dessert arrives, everyone’s too tired (or annoyed) to enjoy it. My friends, this is the problem with single queries in EF Core when they fetch complex relationships. Enter Split Queries, the life of your EF Core dinner party. - [FromSql: Writing SQL Like a Boss in EF Core](https://woodruff.dev/fromsql-writing-sql-like-a-boss-in-ef-core/) - So, you’ve embraced Entity Framework Core, and life’s been good. No more handcrafting SQL for every little query. But what happens when EF Core’s LINQ magic isn’t entirely cutting it? Maybe you need something specific, like a stored procedure or a complex SQL query that LINQ doesn’t handle elegantly. That’s where FromSql swoops in to save the day. - [Compiled Models: The Fast Lane for EF Core Performance](https://woodruff.dev/compiled-models-the-fast-lane-for-ef-core-performance/) - Let’s talk about startup time. Not the Silicon Valley kind, but the time it takes for your EF Core app to boot up, stretch its legs, and actually start handling requests. If your app is dragging its feet like a teenager on a Monday morning, you need a secret weapon: Compiled Models. - [Building with .NET and Rust: A Tale of Two Ecosystems](https://woodruff.dev/building-with-net-and-rust-a-tale-of-two-ecosystems/) - Programming ecosystems are like bustling cities. .NET is the metropolis with skyscrapers and a thriving business district, while Rust is the up-and-coming tech hub—small but mighty, with startups everywhere. Both offer incredible opportunities, but their vibes are very different. So, let’s grab a coffee and tour these two dynamic ecosystems! - [Level Up Your Skills: Learning Rust as a C# Dev](https://woodruff.dev/level-up-your-skills-learning-rust-as-a-c-dev/) - Switching from C# to Rust can feel like stepping into a new world. Suddenly, you’re dealing with ownership, borrowing, and a compiler that’s as strict as your high school math teacher. But don’t worry—you’ve got this. With the right mindset, some practical tips, and a few helpful resources, you’ll go from a Rust rookie to a Rustacean in no time. Let’s dive in! - [DbContext Pooling: The Secret Sauce to Faster EF Core Apps](https://woodruff.dev/dbcontext-pooling-the-secret-sauce-to-faster-ef-core-apps/) - Imagine you’re running a restaurant. Every time a customer orders, you buy a brand-new frying pan, use it once, and toss it out. Sounds absurd, right? But that’s essentially what happens in EF Core when you create a new DbContext for every request. It’s wasteful, slow, and totally unnecessary. Enter DbContext Pooling: the genius way to reuse those frying pans—err, contexts—and turbocharge your app’s performance. - [Announcing My New Book: htmx Essentials for ASP.NET Core Developers](https://woodruff.dev/announcing-my-new-book-htmx-essentials-for-asp-net-core-developers/) - As a developer, you know the web development landscape constantly evolves, and staying ahead means embracing tools and practices that simplify and enhance how we build applications. That's why I'm thrilled to announce my latest project: "htmx Essentials for ASP.NET Core Developers." - [Rust's Superpower: Speed Meets Smarts](https://woodruff.dev/rusts-superpower-speed-meets-smarts/) - Regarding speed and efficiency, Rust doesn’t just run the race—it leaves other languages eating its dust. Built for blazing performance and low-level control, Rust’s unique features make it a standout choice for projects where every millisecond and megabyte count. Let’s dive into why Rust is the Usain Bolt of programming languages and how it stacks up in the performance department. - [From C# to Rust: A Journey Through Code and Concepts](https://woodruff.dev/from-c-to-rust-a-journey-through-code-and-concepts/) - Welcome to my epic blog series, where we pit C# against Rust in a friendly, code-slinging showdown! If you’re a C# developer curious about Rust’s quirks and power or a Rustacean interested in how your language compares to the polished .NET ecosystem, you’ve come to the right place. - [Why Every C# Developer Should Explore Rust](https://woodruff.dev/why-every-c-developer-should-explore-rust/) - Hey there, C# developers! If you’re reading this, you’re probably curious about Rust, that trendy programming language everyone’s been talking about. Maybe you’ve heard whispers of “memory safety” or “no garbage collector” and wondered, “What’s the big deal? Can’t I stick with my trusty .NET stack?” Well, let’s dive in and explore why you, a C# maestro, might want to take a detour into Rust-land. - [Exploring Programming Paradigms: C# and Rust Side by Side](https://woodruff.dev/exploring-programming-paradigms-c-and-rust-side-by-side/) - When it comes to programming languages, each has its quirks, strengths, and unique ways of looking at the world. Think of them as different superheroes with distinct powers. C# is your reliable, well-rounded champion of object-oriented programming (OOP), while Rust is the fearless defender of memory safety and performance. So, how do these two stack up when it comes to their paradigms? Let’s find out! - [Syntax Showdown: A Look at Common Constructs in C# and Rust](https://woodruff.dev/syntax-showdown-a-look-at-common-constructs-in-c-and-rust/) - Programming languages are like different cuisines. Some stick to comfort and tradition, like C# with its familiar object-oriented flavors, while others, like Rust, spice things up with bold new ingredients like ownership and borrowing. In this post, we’ll compare the “syntax recipes” for common constructs in C# and Rust, highlighting the delicious differences and similarities along the way. - [Memory Wars: Garbage Collection in C# vs. Ownership in Rust](https://woodruff.dev/memory-wars-garbage-collection-in-c-vs-ownership-in-rust/) - Regarding memory management, programming languages take different approaches to ensure your applications don’t crash and burn. Think of it as cleaning up after a party: C# hires a janitor (garbage collector) to tidy up for you while Rust hands you a checklist and says, “You’ve got this.” Both methods work, but they have their quirks. Let’s dive into how memory is handled in these two languages and what makes each approach unique. - [Threads, Tasks, and Ownership: C# and Rust Concurrency Explored](https://woodruff.dev/threads-tasks-and-ownership-c-and-rust-concurrency-explored/) - Concurrency in programming can be like cooking dinner while answering emails—you’re juggling multiple tasks at once, hoping nothing burns. C# and Rust both tackle concurrency, but their approaches couldn’t be more different. C# offers a traditional multitasking toolkit with threads and async/await, while Rust rewrites the rulebook with a compiler-enforced, fearless concurrency model. Let’s see how they compare! - [Think Beyond Synchronous: The Ultimate Guide to Tasks in C#](https://woodruff.dev/think-beyond-synchronous-the-ultimate-guide-to-tasks-in-c/) - Imagine you’re cooking dinner. You handle both tasks simultaneously instead of waiting for the water to boil before chopping vegetables. That’s the power of asynchronous programming in C#: enabling your programs to perform multiple operations concurrently, improving performance and responsiveness. The Task class, a cornerstone of modern .NET development, is at the heart of this capability. - [Managing Client Sessions: Tracking and Personalizing Connections](https://woodruff.dev/managing-client-sessions-tracking-and-personalizing-connections/) - In the world of socket programming, managing client sessions is where the magic happens. It’s what transforms a basic connection into a personalized, memorable experience. Whether you’re building a chat application, a multiplayer game, or a real-time dashboard, tracking and managing client sessions is the secret sauce that keeps users engaged and coming back for more. - [Building Bridges: Client-Side Socket Programming in Action](https://woodruff.dev/building-bridges-client-side-socket-programming-in-action/) - Imagine your app is like a curious explorer, eager to reach out into the digital wilderness to gather information, send requests, or simply have a conversation with a server. That’s where client-side socket programming steps in—it’s the bridge that connects your app to the world. - [Real-Time Communication: Effective Data Exchange with Sockets](https://woodruff.dev/real-time-communication-effective-data-exchange-with-sockets/) - Real-time communication is the heartbeat of modern applications, powering everything from video calls to live sports updates. At the core of these dynamic interactions lies the effective exchange of data using sockets. Sockets are the unseen maestros of this symphony, ensuring that data flows seamlessly between clients and servers, even when speed and accuracy are paramount. - [Handling Complexity: Server-Side Socket Programming Explained](https://woodruff.dev/handling-complexity-server-side-socket-programming-explained/) - Handling server-side socket programming is like orchestrating a digital symphony. While the client starts the conversation, the server is the conductor, managing multiple requests, coordinating responses, and ensuring everything stays in harmony. Server-side programming is a mix of art and science—it’s about balancing responsiveness, scalability, and reliability. Let’s break it down and make sense of the complexity. - [C# Socket Programming Essentials: Creating and Configuring Sockets](https://woodruff.dev/c-socket-programming-essentials-creating-and-configuring-sockets/) - If you’ve ever wondered how applications like chat messengers or multiplayer games keep us connected, sockets are the unsung heroes behind the scenes. The concept of socket programming dates back to the early days of the internet, when developers needed a way to establish communication between different devices. In this post, we’ll dive into the essentials of socket programming in C#, focusing on creating and configuring sockets. Whether you’re a seasoned developer or just getting your feet wet in network programming, these fundamentals will help you get started. - [Error Handling and Graceful Shutdowns in Socket Programming](https://woodruff.dev/error-handling-and-graceful-shutdowns-in-socket-programming/) - In the world of socket programming, things don’t always go as planned. Networks are unpredictable, connections drop, and unexpected errors can throw a wrench in the smooth operation of your application. But here’s the good news: with robust error handling and graceful shutdowns, you can keep your application resilient and your users happy, even when things go sideways. - [Socket Types: Choosing the Right Tool for the Job](https://woodruff.dev/socket-types-choosing-the-right-tool-for-the-job/) - Sockets, the unsung architects of digital communication, are each crafted with precision to meet the intricate demands of networking. The right socket choice is not just a technical decision—it’s a transformative step that can elevate your application’s performance from ordinary to extraordinary. With the wrong choice, efficiency crumbles; with the right one, your application thrives, and you, as a professional, are empowered. - [The Backbone of Digital Communication: Understanding the Client-Server Model](https://woodruff.dev/the-backbone-of-digital-communication-understanding-the-client-server-model/) - The client-server model, a ubiquitous presence in our digital universe, is the invisible framework that powers nearly every online interaction you experience. From the seamless streaming of your favorite shows to the lightning-fast loading of websites, this model is the architectural masterpiece orchestrating how devices exchange information in a networked world. It’s the quiet genius behind the scenes, ensuring your digital life feels effortless. - [Demystifying Socket Programming: A Gateway to Networked Applications](https://woodruff.dev/demystifying-socket-programming-a-gateway-to-networked-applications/) - NOTE - This post is an example from the book "Beyond Boundaries: Networking Programming with C# 12 and .NET 8". For a deeper dive into socket programming and more networking concepts, visit https://csharp-networking.com/ or get your copy of the book on Leanpub. Blog Posts in this Series Part 1: Demystifying Socket Programming: A Gateway to Networked Applications Part 2: - [Routing and Topologies – Navigating the Digital Highways](https://woodruff.dev/routing-and-topologies-navigating-the-digital-highways/) - When you send an email, stream a video, or check a social media feed, it's easy to take how that data travels to you for granted. Behind the scenes, an intricate system of routing and network topologies ensures that everything arrives where it's supposed to—fast and error-free. Let's pull back the curtain and take a closer look at how data navigates the digital highways and the role that topologies play in shaping those pathways. - [Decoding IP Addressing and Subnetting – The Backbone of Networking](https://woodruff.dev/decoding-ip-addressing-and-subnetting-the-backbone-of-networking/) - In today's hyper-connected world, where everything from your smartphone to your coffee machine can be online, understanding networking is no longer just for IT pros. At the heart of all this connectivity lies IP addressing and subnetting—the unsung heroes of the digital age. These concepts are the foundation of how devices communicate and share data seamlessly across networks, ensuring everything works. But how does it all happen? Let's break it down. - [Demystifying Network Programming: The Backbone of Modern Applications](https://woodruff.dev/demystifying-network-programming-the-backbone-of-modern-applications/) - Network programming might sound intimidating, but at its core, it’s the art of making applications talk to each other. Whether it’s your favorite messaging app sending texts in real-time or your smartwatch syncing health stats to your phone, network programming is the magic behind it all. It’s not just a technical skill—it’s the backbone of our interconnected digital world. - [Cracking the Code: A Beginner's Guide to Network Protocols](https://woodruff.dev/cracking-the-code-a-beginners-guide-to-network-protocols/) - When you send a text message, watch a video online, or even check your email, countless interactions happen behind the scenes to make it all work seamlessly. These interactions rely on network protocols—a set of rules that ensures devices can talk to each other, even if they're from completely different manufacturers or built for entirely different purposes. - [12 Months, 12 Books: My Yearlong Journey to Learn, Grow, and Level Up](https://woodruff.dev/12-months-12-books-my-yearlong-journey-to-learn-grow-and-level-up/) - As we enter a new year, I’m focusing on personal and professional growth as a developer. The tech industry evolves at breakneck speed, and staying ahead requires more than mastering the latest tools and frameworks. To truly excel, developers must dive deep into their craft, exploring timeless programming principles, leadership, collaboration, and personal development. With their ability to distill the wisdom of experienced professionals, books remain one of the best ways to gain these insights. That’s why I’ve set a personal goal for 2025: to read one transformative book each month. - [I am Self-Publishing the Network Programming Book!](https://woodruff.dev/i-am-self-publishing-the-network-programming-book/) - Last September, I wrote about starting to write a book covering C# 12 and .NET 8 for network programming. I had big hopes with a well-known publisher. It just did not work out because of issues with both sides. It could not happen. So, I took some time off, and after a few months, I - [Compiling Success: My Aspirations for a Transformative Year Ahead](https://woodruff.dev/compiling-success-my-aspirations-for-a-transformative-year-ahead/) - Introduction As we step into 2024, I find myself reflecting on the journey I've embarked upon in the ever-evolving field of software development and architecture. This year, I am setting 10 ambitious goals to grow and expand my life and expertise. I believe that setting clear, achievable objectives is crucial in one’s professional and personal - [The Ultimate Guide to Network Programming in C# 12 & .NET 8](https://woodruff.dev/practical-network-programming-csharp/) - I am thrilled to announce my new adventure into the world of book writing with my upcoming title, "Practical Network Programming Using C#." A few months ago, I received a request about deep diving into network programming, particularly with C#. I am very passionate about this area of software development, so I agreed, and Packt will publish the book. - [The Journey of Self-Discovery: Exploring Your True Self at 50 as a Late Bloomer](https://woodruff.dev/the-journey-of-self-discovery-exploring-your-true-self-at-50-as-a-late-bloomer/) - Late blooming can refer to a person who has experienced a significant change or transformation in their life later on in their years. This change can come from a newfound passion, career, or even a new sense of self. For many late bloomers, this change can bring about a new sense of purpose and fulfillment and be a time of tremendous personal growth. - [Looking at Writing Book Blurbs and How that can Help Conference Speakers](https://woodruff.dev/looking-at-writing-book-blurbs-and-how-that-can-help-conference-speakers/) - "If you are inspiring others to do better, you're successful." - Mod Sun I read a book recently (well, last night, really) that helped me to think about creating conference talks and the abstracts speakers have to craft when they submit their talks to CFPs. The book is "5 Steps to Better Blurbs: Crafting Dynamic - [I asked ChatGPT how to overcome Imposter Syndrome.](https://woodruff.dev/i-asked-chatgpt-how-to-overcome-imposter-syndrome/) - How I am working to overcome Imposter Syndrome. - [New Year and the Art of the Restart](https://woodruff.dev/new-year-and-the-art-of-the-restart/) - My goals and desires fo 2023. ## Pages - [Home](https://woodruff.dev/) - I help teams untangle complexity in software systems. Whether it's modernizing aging platforms or scaling new cloud-native solutions. - [About](https://woodruff.dev/about/) - HomePageAbout Chris Woody Woodruff I Work For Your Incredible Success My Mission My Vision My Goal To simplify the complex and empower others through clear, strategic software architecture and honest technical insight. Whether I'm advising a team, reviewing a system, or testifying in court, my mission is to bring clarity, value, and forward momentum to - [Press & Media](https://woodruff.dev/press-media/) - Press & Media Where has Woody Has Spoken and Shared Ideas Architecting Scalable Cloud Solutions for the Modern Enterprise Chris Woody Woodruff shares his journey and insights on building scalable, cloud-native solutions for modern enterprises—bridging decades of experience with today’s Azure-driven innovations. Rust-ifying Your C# Codebase: A Tale of Adventure and Transformation C# developers: Thinking - [Retainer-Based Services](https://woodruff.dev/retainer-based-services/) - HomePageRetainer-Based Services Retainer-Based Services Service Overview Consistent access to trusted expertise… on your schedule. When you need ongoing architectural support, strategic input, or just a reliable expert to call when it counts, a retainer-based engagement offers flexibility with stability. I partner with your team on a regular cadence, helping you make confident decisions, stay aligned - [Project-Based Contracts](https://woodruff.dev/project-based-contracts/) - HomePageProject-Based Contracts Project-Based Contracts Service Overview Focused outcomes. Defined scope. Real results. When you need a clear technical deliverable, a project-based engagement is the best fit. Whether it’s an architecture redesign, performance remediation, or a modernization roadmap, I deliver end-to-end technical work with a defined beginning, middle, and end, and clear success criteria. You get - [Micro-Consulting](https://woodruff.dev/micro-consulting/) - HomePageMicro-Consulting Micro-Consulting Service Overview High-value insights—without the overhead. Micro-consulting is designed for teams who need answers fast. Whether you’re facing a critical decision, a complex technical challenge, or just need a second set of expert eyes, I offer focused consulting engagements that deliver clarity and direction within hours, not weeks. No long-term contracts, no fluff—just - [Fractional Architect](https://woodruff.dev/fractional-architect/) - HomePageFractional Architect Fractional Architect Service Overview High-impact software architecture… when and how you need it. Not every organization needs a full-time architect, but every growing team needs architectural guidance. As a Fractional Architect, I partner with you to provide technical leadership, platform strategy, and architectural clarity—on a flexible schedule and at a fraction of the - [Software Forensic Expert Witness](https://woodruff.dev/expert-witness/) - HomePageSoftware Forensic Expert Witness Software Forensic Expert Witness Service Overview Clear, objective software analysis—when the stakes are high. When software is at the center of a legal dispute, clarity matters. As a Software Forensic Expert Witness, I bring decades of architectural and development experience to uncover what happened, how it happened, and why it matters. - [Contact](https://woodruff.dev/contact/) - Get In Touch I will contact you after receive your request in 24h +1 616.724.6885 chris@woodruff.dev Wyoming MI 49418 Set up a 1:1 with Chris Woody Woodruff today! The field is required mark as * Name Email Phone Company Subject Your inquiry aboutFractional LeadershipAdvisory & Board RolesConsultingLegal Work Message (optional) This form uses Akismet to - [Advisory & Board Roles](https://woodruff.dev/advisory-board-roles/) - HomePageAdvisory & Board Roles Advisory & Board Roles Service Overview Strategic technical insight at the leadership level. As a technology advisor or board member, I bring a software architect’s mindset to strategic planning, platform decisions, and innovation initiatives. I help organizations navigate complex technical landscapes, assess risk, validate decisions, and future-proof their technology direction—all while - [404 Page](https://woodruff.dev/404-page/) - Opps! Looks Like Here is Nothing. The page you’re looking for isn’t found. We suggest you back to home. It’s easy... Back To Home - [Books](https://woodruff.dev/books-2/) - Books Beyond Boundaries - Networking Programming with C#12 and .NET 8 “Beyond Boundaries – Networking Programming with C# 12 and .NET 8” is your ultimate guide to mastering the art of network programming in modern .NET applications. Designed for developers of all skill levels, this book takes you on a journey through networking fundamentals. It gradually - [Privacy Policy](https://woodruff.dev/privacy-policy-2/) - Effective Date: January 29, 2025 Welcome to Chris Woodruff's Personal Website (the "Website"). Your privacy is important to me. This Privacy Policy explains how I collect, use, and protect information about visitors to this Website. 1. Information Collected I use Google Analytics to gather information about how visitors interact with the Website. This includes: Pages ## Portfolio - [Entity Framework Core Course](https://woodruff.dev/portfolio/entity-framework-core-course/) - Entity Framework Core Course Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the top - [ASP.NET Web API Course](https://woodruff.dev/portfolio/hemera-ios-app-design-4/) - ASP.NET Web API Course Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the top - [Beyond Boundaries - Networking Programming with C# 12 and .NET 8](https://woodruff.dev/portfolio/csharp-networking-book/) - Beyond Boundaries - Networking Programming with C# 12 and .NET 8 Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, - [ASP.NET Core Reimagined with htmx](https://woodruff.dev/portfolio/aspnet-core-htmx-book/) - ASP.NET Core Reimagined with htmx Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the - [The Woody Show](https://woodruff.dev/portfolio/the-woody-show/) - Notero - Easy Notes App Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the - [The Breakpoint Show](https://woodruff.dev/portfolio/the-breakpoint-show/) - Notero - Easy Notes App Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the - [ASP.NET Web API Workshop](https://woodruff.dev/portfolio/asp-net-web-api-workshop/) - ASP.NET Web API Workshop Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the top - [Entity Framework Core Workshop](https://woodruff.dev/portfolio/entity-framework-core-workshop/) - Entity Framework Core Workshop Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the top - [Terraform Workshop](https://woodruff.dev/portfolio/terraform-workshop/) - Terraform Workshop Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the top of the - [htmx & Razor Pages Workshop](https://woodruff.dev/portfolio/htmx-razor-pages-workshop/) - htmx & Razor Pages Workshop Client Microsoft Holing Ltd, Australia Area Services IT Consultation, Design, Cloud Service Date February 25th, 2022 Release started Team Designers - Developers Operators - Manager Stay focused and productive with a clean and clutter-free note space. The flexible ways to organize your notes: hashtags, nested notebooks, pinning notes to the ## Custom Footer - [Footer](https://woodruff.dev/footer/footer/) - Shall we have a chat? If you have a project or collaboration that you would like to discuss with us, or if you are curious to hear more about how we can help you, we look forward to hearing from you. info@webexample.com +908 (908) 678 77 Copyright & Design By @ThemesCamp – 2022 Facebook-f Twitter Behance Youtube ## Categories - [Blog](https://woodruff.dev/category/blog/) - [Speaking](https://woodruff.dev/category/speaking/) - [Random C#](https://woodruff.dev/category/blog/random-csharp/) - [Network Book Sample](https://woodruff.dev/category/blog/network-book-sample/) - [Rust](https://woodruff.dev/category/blog/rust/) - [Entity Framework Core](https://woodruff.dev/category/blog/efcore/) - [Terraform](https://woodruff.dev/category/blog/terraform/) - [HTTP REST](https://woodruff.dev/category/blog/http-rest/) - [htmx](https://woodruff.dev/category/blog/htmx/) - [Genetic Algorithms](https://woodruff.dev/category/blog/genetic-algorithms/) - [AI](https://woodruff.dev/category/blog/ai/) - [Business of Software](https://woodruff.dev/category/blog/biz-software/) - [Simplicity-First](https://woodruff.dev/category/blog/simplicity-first/) - [fun tech](https://woodruff.dev/category/blog/fun-tech/) - [Patterns](https://woodruff.dev/category/blog/patterns/) - [Developer Experience](https://woodruff.dev/category/blog/developer-experience/) ## Tags - [personal](https://woodruff.dev/tag/personal/) - [2023](https://woodruff.dev/tag/2023/) - [goals](https://woodruff.dev/tag/goals/) - [imposter syndrome](https://woodruff.dev/tag/imposter-syndrome/) - [better me](https://woodruff.dev/tag/better-me/) - [speaking](https://woodruff.dev/tag/speaking/) - [creating talks](https://woodruff.dev/tag/creating-talks/) - [talk abstracts](https://woodruff.dev/tag/talk-abstracts/) - [EF Core](https://woodruff.dev/tag/ef-core/) - [Data](https://woodruff.dev/tag/data/) - [.NET](https://woodruff.dev/tag/net/) - [Book](https://woodruff.dev/tag/book/) - [C#](https://woodruff.dev/tag/c/) - [dotnet](https://woodruff.dev/tag/dotnet/) - [network](https://woodruff.dev/tag/network/) - [programming](https://woodruff.dev/tag/programming/) - [development](https://woodruff.dev/tag/development/) - [personal journey](https://woodruff.dev/tag/personal-journey/) - [books](https://woodruff.dev/tag/books/) - [developers](https://woodruff.dev/tag/developers/) - [new year](https://woodruff.dev/tag/new-year/) - [reading](https://woodruff.dev/tag/reading/) - [learning](https://woodruff.dev/tag/learning/) - [rust](https://woodruff.dev/tag/rust/) - [databases](https://woodruff.dev/tag/databases/) - [Entity Framework Core](https://woodruff.dev/tag/entity-framework-core/) - [asp.net](https://woodruff.dev/tag/asp-net/) - [web development](https://woodruff.dev/tag/web-development/) - [htmx](https://woodruff.dev/tag/htmx/) - [terraform](https://woodruff.dev/tag/terraform/) - [devops](https://woodruff.dev/tag/devops/) - [IaC](https://woodruff.dev/tag/iac/) - [infrastructure](https://woodruff.dev/tag/infrastructure/) - [spatial](https://woodruff.dev/tag/spatial/) - [Azure](https://woodruff.dev/tag/azure/) - [simplicity-first](https://woodruff.dev/tag/simplicity-first/) - [software philosophy](https://woodruff.dev/tag/software-philosophy/) - [design](https://woodruff.dev/tag/design/) - [architectur](https://woodruff.dev/tag/architectur/) - [HTTP](https://woodruff.dev/tag/http/) - [REST](https://woodruff.dev/tag/rest/) - [webdev](https://woodruff.dev/tag/webdev/) - [asp.net core](https://woodruff.dev/tag/asp-net-core/) - [ai](https://woodruff.dev/tag/ai/) - [genetic algorithms](https://woodruff.dev/tag/genetic-algorithms/) - [business of software](https://woodruff.dev/tag/business-of-software/) - [architecture](https://woodruff.dev/tag/architecture/) - [github](https://woodruff.dev/tag/github/) - [scripting](https://woodruff.dev/tag/scripting/) - [python](https://woodruff.dev/tag/python/) - [open-source](https://woodruff.dev/tag/open-source/) - [law](https://woodruff.dev/tag/law/) - [licensing](https://woodruff.dev/tag/licensing/) - [patterns](https://woodruff.dev/tag/patterns/) - [MSSQL](https://woodruff.dev/tag/mssql/) - [distributed](https://woodruff.dev/tag/distributed/) - [systems thinking](https://woodruff.dev/tag/systems-thinking/) - [htmxRazor](https://woodruff.dev/tag/htmxrazor/) - [wed components](https://woodruff.dev/tag/wed-components/) - [UX](https://woodruff.dev/tag/ux/) - [IDEs](https://woodruff.dev/tag/ides/) ## Portfolio Categories - [Book](https://woodruff.dev/portfolio_category/books/) - [Podcast](https://woodruff.dev/portfolio_category/podcasts/) - [Course](https://woodruff.dev/portfolio_category/courses/) ## Portfolio Tags - [Open-Source](https://woodruff.dev/porto_tag/open-source/)