Moonglade’s migration from Azure Communication Services to Resend provided an opportunity to simplify its email architecture and reduce vendor lock-in. Instead of introducing another vendor-specific SDK, the application now uses a single SMTP implementation, removing the Azure integration, provider dispatcher, and related configuration branches.
Moonglade has replaced its Entra ID-specific authentication implementation with standard OpenID Connect. Entra ID still works, but it is now just one OIDC provider among many. This change simplifies the authentication architecture, separates authentication from authorization, and makes Moonglade easier to run beyond Azure.
Moonglade has redesigned its image storage architecture by removing direct dependencies on Azure Blob Storage and S3-compatible SDKs. The application now works with two isolated filesystem roots for public images and private originals, while the hosting environment provides durable storage through Azure Files, Docker volumes, NFS, or other mounted solutions. This change reduces provider-specific code and configuration, strengthens the security boundary around original uploads, and makes the blog easier to deploy across different platforms without sacrificing CDN support.
This post explains how Moonglade moved its email notification system away from a standalone Azure Functions service and Azure Storage Queue, integrating email processing back into the main blog application with a lightweight database outbox. The migration reduces Azure dependencies and deployment complexity while keeping email delivery asynchronous, durable, and reliable for a personal blogging workload.
Recently, I developed an ASP.NET Core application that can query a local data file for IP address information. The application is deployed to Azure Container Apps, and the data file is mounted in Azure File Share as a volume for the container. There is another job that will update the data file every day on schedule. The application would not read the entire data file on each request for performance concerns, it would load the data into memory on start up. The blog post will explain how to reload the data on the fly without downtime.
This blog runs on my open-source project Moonglade, a blogging platform built with ASP.NET Core and hosted on Azure. Recently, I migrated it from a Windows Server environment to Docker on Linux, still running on Azure App Service. It’s been running smoothly in production for about two months now. In this post, I’ll walk through that migration journey: what I changed, a few tips and tricks along the way, and some lessons learned that might help you if you’re considering a similar move.
When preparing for interviews, you'll often come across optimization problems that test both your problem-solving skills and your ability to write efficient code. I have such an interesting programming interview question years ago. The Efficient Shipping problem. Let's break it down and analyze the solution. And to understand the flaws in the first version of my code and how we can improve it.
Moonglade.Email, is an Azure Function that originally relied on SMTP for sending emails. Microsoft implemented a change that prevents connections to both personal and enterprise Office 365 Outlook mailboxes. To ensure the email service continues functioning, I decided to integrate Azure Communication Services. In this blog post, I will explain how I implemented support for Azure Communication Services in the Moonglade.Email Azure Function.