<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Vitor Aleluia</title><description>Personal blog covering software engineering, systems architecture, and developer tooling.</description><link>https://vitoraleluia.com/</link><language>en-us</language><item><title>Welcome to My Blog: Engineering, Architecture, and Notes</title><link>https://vitoraleluia.com/blog/welcome-to-my-blog/</link><guid isPermaLink="true">https://vitoraleluia.com/blog/welcome-to-my-blog/</guid><description>An introduction to this website, why I decided to build it with Astro, and what I plan to share here.</description><pubDate>Tue, 15 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to my personal website and blog!&lt;/p&gt;
&lt;p&gt;For a long time, I’ve wanted a focused, distraction-free space on the internet to document what I’m learning, publish deep-dives into software engineering topics, and organize links to my work.&lt;/p&gt;
&lt;h2&gt;Why Astro?&lt;/h2&gt;
&lt;p&gt;When deciding how to build this space, my requirements were straightforward:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Speed and zero runtime bloat:&lt;/strong&gt; Static HTML generation with minimal client-side JavaScript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;First-class Markdown &amp;amp; MDX support:&lt;/strong&gt; Writing technical articles should be as friction-free as creating a Markdown document in my code editor.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Typography &amp;amp; Readability:&lt;/strong&gt; A reading experience inspired by editorial blogs like &lt;em&gt;Akita on Rails&lt;/em&gt; and minimalist portfolios like &lt;em&gt;Vasilios Syrakis&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Astro provides the perfect foundation. Paired with Starlight’s search engine (Pagefind) and expressive code highlighting, the site delivers blazing-fast performance and seamless dark mode by default.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Clean, minimal site configuration
export const siteConfig = {
  name: &apos;Vitor Aleluia&apos;,
  focus: [&apos;Systems Architecture&apos;, &apos;Distributed Systems&apos;, &apos;Developer Tooling&apos;],
  theme: &apos;dark&apos;,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;What You’ll Find Here&lt;/h2&gt;
&lt;p&gt;On this blog, I will be writing about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Systems Architecture:&lt;/strong&gt; Resilient distributed architectures, database trade-offs, and edge networking.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Developer Tooling:&lt;/strong&gt; Workflows, compilers, type systems, and building tools that make engineers more productive.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reflections &amp;amp; Notes:&lt;/strong&gt; Real-world lessons from scaling systems and navigating software development.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to explore the &lt;a href=&quot;/links/&quot;&gt;Links&lt;/a&gt; page to connect on GitHub, LinkedIn, or via email. Thanks for reading!&lt;/p&gt;
</content:encoded></item><item><title>Pragmatic Lessons in Distributed Systems &amp; Reliability</title><link>https://vitoraleluia.com/blog/building-distributed-systems/</link><guid isPermaLink="true">https://vitoraleluia.com/blog/building-distributed-systems/</guid><description>Observations and trade-offs learned while designing resilient backend services and dealing with edge networking.</description><pubDate>Wed, 02 Sep 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When building distributed services, the fallacies of distributed computing remain ever-present: the network is never reliable, latency is never zero, and bandwidth is never infinite.&lt;/p&gt;
&lt;p&gt;In this post, I want to outline three foundational lessons that have repeatedly proven valuable when architecting systems that must withstand failure gracefully.&lt;/p&gt;
&lt;h2&gt;1. Design for Partial Degradation&lt;/h2&gt;
&lt;p&gt;A common failure mode in modern microservices is cascading failures. If service A calls service B synchronously, and service B begins timing out, thread pools or connection pools on service A quickly become exhausted.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Implementing circuit breaking and exponential backoff
pub async fn call_with_retry&amp;lt;T, F, Fut&amp;gt;(mut operation: F, max_retries: u32) -&amp;gt; Result&amp;lt;T, SystemError&amp;gt;
where
    F: FnMut() -&amp;gt; Fut,
    Fut: std::future::Future&amp;lt;Output = Result&amp;lt;T, SystemError&amp;gt;&amp;gt;,
{
    let mut attempt = 0;
    let mut delay = std::time::Duration::from_millis(50);

    loop {
        match operation().await {
            Ok(val) =&amp;gt; return Ok(val),
            Err(e) if attempt &amp;gt;= max_retries =&amp;gt; return Err(e),
            Err(_) =&amp;gt; {
                attempt += 1;
                tokio::time::sleep(delay).await;
                delay *= 2;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instead of allowing an outage in one subsystem to take down the entire application, every remote call should adhere to three non-negotiable rules:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Strict, bounded timeouts:&lt;/strong&gt; Never rely on defaults. Default HTTP timeouts are often infinite or measured in minutes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Circuit breaking:&lt;/strong&gt; Stop hammering a failing downstream dependency.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful degradation:&lt;/strong&gt; Provide a cached response, a stale fallback, or an informative degraded UI rather than an uncaught 500 error.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Idempotency at Every Layer&lt;/h2&gt;
&lt;p&gt;Networks duplicate packets, proxies retry requests, and message brokers deliver messages at-least-once. If your mutation APIs cannot safely receive the same request twice, you are guaranteed to corrupt data eventually.&lt;/p&gt;
&lt;p&gt;Introducing an &lt;code&gt;Idempotency-Key&lt;/code&gt; header on all modifying requests ensures that even if a network timeout causes the client to resend, the operation is executed exactly once.&lt;/p&gt;
&lt;h2&gt;3. Observability is More Than Raw Metrics&lt;/h2&gt;
&lt;p&gt;Dashboards with hundreds of graphs often obscure reality rather than illuminate it. What matters during an incident is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;High-cardinality distributed tracing (where is time being spent?)&lt;/li&gt;
&lt;li&gt;Structured logs with correlation IDs.&lt;/li&gt;
&lt;li&gt;SLO-based alerts tied directly to user experience (e.g. error rate percentage and P99 latency thresholds).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Investing in thoughtful observability early transforms debugging from speculative guesswork into targeted resolution.&lt;/p&gt;
</content:encoded></item><item><title>Developer Ergonomics: Blending TypeScript with Rust</title><link>https://vitoraleluia.com/blog/developer-ergonomics-with-rust-and-typescript/</link><guid isPermaLink="true">https://vitoraleluia.com/blog/developer-ergonomics-with-rust-and-typescript/</guid><description>How combining type safety and zero-cost abstractions across stacks elevates developer ergonomics and system reliability.</description><pubDate>Tue, 18 Aug 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Writing robust software doesn’t have to come at the expense of developer happiness. Over the past several years, the software engineering landscape has seen a significant shift towards expressive, static type systems.&lt;/p&gt;
&lt;p&gt;Two technologies in particular stand out in how they enhance engineering velocity while eliminating entire classes of bugs: &lt;strong&gt;TypeScript&lt;/strong&gt; on the application layer, and &lt;strong&gt;Rust&lt;/strong&gt; on the systems and performance layer.&lt;/p&gt;
&lt;h2&gt;The Power of Discriminated Unions&lt;/h2&gt;
&lt;p&gt;One of the greatest gifts of TypeScript’s type system is algebraic data types represented through discriminated unions. Rather than passing nullable fields and hoping callers inspect them, we make invalid states unrepresentable:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Result&amp;lt;T, E&amp;gt; =
  | { success: true; data: T }
  | { success: false; error: E };

function handleApiResponse(response: Result&amp;lt;{ id: string }, Error&amp;gt;) {
  if (response.success) {
    // TypeScript automatically narrows the type here
    console.log(&quot;Resource created:&quot;, response.data.id);
  } else {
    console.error(&quot;Operation failed:&quot;, response.error.message);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This pattern maps directly to Rust’s native &lt;code&gt;Result&amp;lt;T, E&amp;gt;&lt;/code&gt; enum, making mental context switching between the two languages remarkably intuitive.&lt;/p&gt;
&lt;h2&gt;Bringing Native Performance to Tooling&lt;/h2&gt;
&lt;p&gt;In developer tooling, performance is a feature. When test runners, linters, or code generators take minutes, developers lose their flow state. By rewriting critical paths in Rust or leveraging WebAssembly, we can compress feedback loops from minutes to milliseconds.&lt;/p&gt;
&lt;p&gt;The future of software tooling is fast, type-safe, and delightful to use.&lt;/p&gt;
</content:encoded></item></channel></rss>