<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Paul Fernandez · Thoughts</title><description>Opinions, notes, and lessons from shipping national scale platforms.</description><link>https://janpaulfernandez.com/</link><item><title>The Architecture of Under-Pressure Systems: PHVote 2019</title><link>https://janpaulfernandez.com/thoughts/architecture-under-pressure/</link><guid isPermaLink="true">https://janpaulfernandez.com/thoughts/architecture-under-pressure/</guid><description>How we designed Rappler&apos;s election-night canvas systems to handle millions of views under pressure.</description><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;bg-alert-terracotta-600 text-beige-50 p-6 md:p-8 my-8 rounded-2xl shadow-lg relative overflow-hidden&quot;&gt; &lt;div class=&quot;flex items-center gap-2 font-display text-xs tracking-widest uppercase text-citrus-300 mb-3&quot;&gt; &lt;span&gt;★&lt;/span&gt; &lt;span&gt;Key Takeaway&lt;/span&gt; &lt;/div&gt; &lt;div class=&quot;prose max-w-none text-beige-50 font-medium leading-relaxed [&amp;&gt;p]:text-beige-50 [&amp;&gt;p]:m-0&quot;&gt; &lt;p&gt;Building systems that survive under pressure requires prioritizing static distribution, minimizing run-time database operations, and decoupling data collection from presentation.&lt;/p&gt; &lt;/div&gt; &lt;/div&gt;
&lt;p&gt;On election nights in the Philippines, newsroom traffic doesn’t just increase; it spikes vertically. Within a matter of minutes, as polls close and the first precinct tallies begin to transmit from optical scan machines to municipal and national servers, millions of citizens flock to news sites for real-time visualization of the results.&lt;/p&gt;
&lt;p&gt;In 2019, leading the technology operations at Rappler, we were tasked with building &lt;strong&gt;PHVote 2019&lt;/strong&gt;, the platform that would ingest the raw data streams from the Commission on Elections (COMELEC) and present them to the public. The constraint was absolute: the system could not fail. In media, downtime during a national election is not merely a technical glitch—it is a failure of public trust.&lt;/p&gt;
&lt;p&gt;Here is how we designed a system that held up under pressure, focusing on decoupling, strict static delivery, and managing the human psychology of engineering teams under fire.&lt;/p&gt;
&lt;h2 id=&quot;ingestion-vs-presentation-the-great-wall&quot;&gt;Ingestion vs. Presentation: The Great Wall&lt;a aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot; class=&quot;anchor-link ml-2 text-moss-200 hover:text-moss-500 transition-colors&quot; href=&quot;#ingestion-vs-presentation-the-great-wall&quot;&gt;&lt;span class=&quot;anchor-icon&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The classic failure mode of high-traffic web applications is the shared database. A typical user request hits an application server, which queries a database, formats the result, and returns it. Under normal load, this is fast enough. Under election-night load, the database locks up, connection pools exhaust, and the site crashes.&lt;/p&gt;
&lt;p&gt;Our first architectural decision was to build a complete separation between our &lt;strong&gt;Ingestion Pipeline&lt;/strong&gt; and our &lt;strong&gt;Presentation Layer&lt;/strong&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8;overflow-x:auto&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[COMELEC Media Server] &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         │ (Ingestion: Secure, private)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;         ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;[Ingestion Engine] ──(Generates static JSON/HTML)──► [Cloud Storage Bucket]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                                                               │ (CDN edge cache)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                                                               ▼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;                                                       [Public Browser]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The Ingestion Engine ran on a private, isolated network. It queried the COMELEC media server, validated the incoming data packets for schema correctness, and computed the aggregated statistics. Crucially, the Ingestion Engine did &lt;em&gt;not&lt;/em&gt; serve web traffic.&lt;/p&gt;
&lt;p&gt;Instead, it transformed the data into static files (JSON and HTML) and pushed them directly to cloud storage (Google Cloud Storage / Amazon S3). The public-facing website was entirely static. When a user visited the page, their browser requested these static files directly from the Content Delivery Network (CDN) edge.&lt;/p&gt;
&lt;div class=&quot;p-6 md:p-7 my-8 rounded-2xl bg-alert-light-blue-100 text-ink border border-ink/10 shadow-sm&quot;&gt; &lt;div class=&quot;flex items-center gap-2 font-display text-xs tracking-widest uppercase mb-3 text-alert-terracotta-600&quot;&gt; &lt;span&gt;📝&lt;/span&gt; &lt;span&gt;Note&lt;/span&gt; &lt;/div&gt; &lt;div class=&quot;prose max-w-none font-medium leading-relaxed [&amp;#38;&gt;p]:m-0 text-ink [&amp;#38;&gt;p]:text-ink&quot;&gt; &lt;p&gt;By serving static assets directly from edge caches, we reduced database queries to exactly zero for public visitors, transferring the scaling burden completely to global CDN infrastructures.&lt;/p&gt; &lt;/div&gt; &lt;/div&gt;
&lt;p&gt;This separation meant that even if our public site received ten million concurrent hits, the load on our ingestion server remained constant. The ingestion engine only had to write the updated static files once every few minutes when new transmission batches arrived.&lt;/p&gt;
&lt;h2 id=&quot;invalidation-at-the-edge&quot;&gt;Invalidation at the Edge&lt;a aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot; class=&quot;anchor-link ml-2 text-moss-200 hover:text-moss-500 transition-colors&quot; href=&quot;#invalidation-at-the-edge&quot;&gt;&lt;span class=&quot;anchor-icon&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Decoupling ingestion from presentation solved the database load problem, but it introduced a new challenge: cache invalidation. How do we ensure that users see the latest results without overloading the origin when millions of browsers request updates?&lt;/p&gt;
&lt;p&gt;Standard TTL (Time-to-Live) caching was insufficient. If we set the TTL to 10 seconds, millions of users would re-request the file from the origin every 10 seconds. If we set it to 10 minutes, the data would feel stale, prompting users to manually refresh, exacerbating traffic.&lt;/p&gt;
&lt;p&gt;We solved this using &lt;strong&gt;Stale-While-Revalidate (SWR)&lt;/strong&gt; and targeted cache invalidation headers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Surrogate Keys:&lt;/strong&gt; We tagged every generated static resource with specific metadata headers (e.g., &lt;code&gt;Surrogate-Key: topic-national-results&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instant Purges:&lt;/strong&gt; When our ingestion pipeline wrote an updated file, it fired an API call to our CDN provider to instantly purge only the specific surrogate key that changed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful Degraded States:&lt;/strong&gt; If the ingestion engine went offline temporarily, the CDN was configured to serve stale cached content rather than a 502/504 error page.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;relative py-8 my-8 border-y border-moss-200/40 text-center&quot;&gt; &lt;span class=&quot;absolute top-2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-beige-100 px-3 text-moss-500 font-display text-4xl leading-none select-none&quot;&gt;“&lt;/span&gt; &lt;blockquote class=&quot;font-display text-xl md:text-2xl text-moss-900 leading-relaxed max-w-2xl mx-auto&quot;&gt; &lt;p&gt;“The cost of a database query on election night is not measured in milliseconds; it is measured in lost trust.”&lt;/p&gt; &lt;/blockquote&gt; &lt;/div&gt;
&lt;p&gt;This approach ensured that updates were pushed to the edge instantly, while preserving the protective barrier of the CDN.&lt;/p&gt;
&lt;h2 id=&quot;the-psychology-of-high-stakes-operations&quot;&gt;The Psychology of High-Stakes Operations&lt;a aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot; class=&quot;anchor-link ml-2 text-moss-200 hover:text-moss-500 transition-colors&quot; href=&quot;#the-psychology-of-high-stakes-operations&quot;&gt;&lt;span class=&quot;anchor-icon&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Technical architecture is only half the battle. The other half is the human element. Under high stress, engineers make mistakes. We designed our deployment workflows to minimize cognitive load on the team.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Command Isolation:&lt;/strong&gt; During the 72 hours surrounding election night, we instituted a strict code freeze. No feature changes were allowed. Deployments were restricted to infrastructure scale-up commands.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runbook Redundancy:&lt;/strong&gt; We documented every possible failure mode—e.g., COMELEC stream stalls, CDN edge failure, regional routing blocks—in clear, checkbox-driven runbooks. When things went wrong, engineers didn’t have to think; they just had to follow the checklist.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simulation Days:&lt;/strong&gt; Two weeks before the election, we simulated a total COMELEC feed failure and forced the team to recover the site using offline backup streams.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ultimately, PHVote 2019 delivered the fastest and most stable results visualization in the country that year, with 100% uptime throughout the critical 48-hour peak.&lt;/p&gt;
&lt;h2 id=&quot;lessons-for-enterprise-ai-and-digital-transformation&quot;&gt;Lessons for Enterprise AI and Digital Transformation&lt;a aria-hidden=&quot;true&quot; tabindex=&quot;-1&quot; class=&quot;anchor-link ml-2 text-moss-200 hover:text-moss-500 transition-colors&quot; href=&quot;#lessons-for-enterprise-ai-and-digital-transformation&quot;&gt;&lt;span class=&quot;anchor-icon&quot;&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While election coverage is a unique event, the principles of under-pressure systems apply directly to corporate digital transformation.&lt;/p&gt;
&lt;p&gt;Organizations seeking to implement AI inside their legacy workflows often try to build complex, real-time middleware that connects legacy core databases to LLM models. This creates unstable dependencies. By applying the “Great Wall” separation—staging operational data into static, pre-processed cache layers before exposing them to AI agents—companies can adopt AI securely without risking core system outages.&lt;/p&gt;
&lt;div class=&quot;aspect-video w-full my-6 overflow-hidden rounded-lg border border-moss-200&quot;&gt; &lt;iframe src=&quot;https://www.youtube.com/embed/dQw4w9WgXcQ&quot; title=&quot;PHVote 2019 System Architecture Retrospective&quot; class=&quot;w-full h-full&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen loading=&quot;lazy&quot;&gt;&lt;/iframe&gt; &lt;/div&gt;</content:encoded></item><item><title>AI inside the Enterprise: Realism vs Hype</title><link>https://janpaulfernandez.com/thoughts/ai-enterprise-realism/</link><guid isPermaLink="true">https://janpaulfernandez.com/thoughts/ai-enterprise-realism/</guid><description>Why real enterprise AI implementation is about simple workflows and internal APIs, not multi-million dollar model training.</description><pubDate>Thu, 25 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Enterprise AI has a marketing problem. If you listen to major software vendors, digital transformation in 2026 requires building custom LLMs, training foundation models from scratch on your private PDFs, or setting up multi-million dollar vector databases.&lt;/p&gt;
&lt;p&gt;In practice, for 95% of businesses, this is a waste of money and time.&lt;/p&gt;
&lt;p&gt;The real value of AI in the enterprise lies in &lt;strong&gt;workflow integration&lt;/strong&gt;. It is about taking standard, off-the-shelf API models (like Gemini or Claude) and inserting them into very specific, small operational pipelines:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Incoming Customer Support routing:&lt;/strong&gt; Categorizing emails and tickets into high/medium/low priority based on sentiment and intent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document Extraction:&lt;/strong&gt; Pulling structured data from PDFs (invoices, shipping slips) and pasting them into ERP systems.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Search Synthesis:&lt;/strong&gt; Allowing internal staff to query policy handbooks with reference citations.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You don’t need a team of Ph.D. research scientists for this. You need a couple of senior full-stack developers who understand schemas, security, and prompt orchestration. Keep the models commoditized and build the value in your application layer.&lt;/p&gt;</content:encoded></item><item><title>Cognitive Load and Team Topologies</title><link>https://janpaulfernandez.com/thoughts/cognitive-load-team-layouts/</link><guid isPermaLink="true">https://janpaulfernandez.com/thoughts/cognitive-load-team-layouts/</guid><description>Why small, decoupled teams beat monolithic reporting lines, and how Conway&apos;s law affects tech architecture.</description><pubDate>Sat, 20 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In software engineering, we often talk about system architecture in terms of servers, load, and data models. But the most constrained resource in any technology organization is actually &lt;strong&gt;human cognitive load&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When an engineering team is responsible for too many things—e.g., maintaining legacy billing systems, building new consumer features, and managing Kubernetes clusters—they spend all their time context switching. Quality drops, deployments slow down, and burnout rises.&lt;/p&gt;
&lt;p&gt;According to Conway’s Law, organizations design systems that copy their communication structures. If you have a single monolithic engineering department with everyone working on everything, you will inevitably build a monolithic, tightly coupled codebase.&lt;/p&gt;
&lt;p&gt;The solution is to restructure teams around &lt;strong&gt;bounded contexts&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep teams focused on single, cohesive domain areas.&lt;/li&gt;
&lt;li&gt;Define strict, stable interface APIs between teams (rather than loose ad-hoc Slack coordination).&lt;/li&gt;
&lt;li&gt;Minimize coordination overhead so teams can deploy independently.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to speed up your software delivery, don’t buy a faster CI/CD server. Fix your organizational layout to respect your engineers’ mental capacity.&lt;/p&gt;</content:encoded></item></channel></rss>