<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kiell Tampubolon</title>
    <description>The latest articles on Forem by Kiell Tampubolon (@kielltampubolon).</description>
    <link>https://forem.com/kielltampubolon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3890870%2Ff4c1760b-670f-4d29-b0a8-29dc39842afa.jpg</url>
      <title>Forem: Kiell Tampubolon</title>
      <link>https://forem.com/kielltampubolon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kielltampubolon"/>
    <language>en</language>
    <item>
      <title>What's New in GKE at Next '26: Kubernetes Just Got Smarter (and Cheaper)</title>
      <dc:creator>Kiell Tampubolon</dc:creator>
      <pubDate>Thu, 23 Apr 2026 14:01:43 +0000</pubDate>
      <link>https://forem.com/kielltampubolon/whats-new-in-gke-at-next-26-kubernetes-just-got-smarter-and-cheaper-1md</link>
      <guid>https://forem.com/kielltampubolon/whats-new-in-gke-at-next-26-kubernetes-just-got-smarter-and-cheaper-1md</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-cloud-next-2026-04-22"&gt;Google Cloud NEXT Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes as the OS of the AI Era
&lt;/h2&gt;

&lt;p&gt;At Google Cloud Next '26, Google made one thing pretty clear: &lt;strong&gt;Kubernetes is no longer just a container orchestrator. It's quickly becoming the operating system of the AI era.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The numbers speak for themselves. GKE now powers AI workloads for all of Google's top 50 customers on the platform, including the biggest frontier model builders out there. In just a few months, multi-agent AI workflows surged by &lt;strong&gt;327%&lt;/strong&gt;. On top of that, 66% of organizations now rely on Kubernetes to run their generative AI apps and agents.&lt;/p&gt;

&lt;p&gt;This isn't just an incremental update. It's a real shift. And the GKE announcements at Next '26 reflect that change well. Here's a breakdown of what's new and why it actually matters for developers.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. GKE Agent Sandbox: Secure, Scalable Agent Infrastructure
&lt;/h2&gt;

&lt;p&gt;As AI moves from chatbots to fully autonomous agents running at massive scale, the underlying infrastructure needs to keep up with hundreds, sometimes thousands, of agents collaborating at the same time.&lt;/p&gt;

&lt;p&gt;Google's answer to this is the &lt;strong&gt;GKE Agent Sandbox&lt;/strong&gt;, which they're calling the industry's most scalable and low-latency agent infrastructure. It's built on &lt;strong&gt;gVisor kernel isolation&lt;/strong&gt; (the same tech that secures Gemini), so you can safely run untrusted code, tools, and entire agents without giving up performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key numbers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;300 sandboxes per second at sub-second latency&lt;/li&gt;
&lt;li&gt;Up to 30% better price-performance on Axion compared to other hyperscale clouds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One real-world example: &lt;strong&gt;Lovable&lt;/strong&gt;, a platform where builders spin up 200,000+ new projects every single day, runs its AI-generated apps in GKE Agent Sandboxes. The reason? Fast startup, fast scaling, and solid secure isolation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt; If you're building multi-agent systems or executing untrusted user-generated code, Agent Sandbox takes away the painful choice between security and speed.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. GKE Hypercluster: One Control Plane for Everything
&lt;/h2&gt;

&lt;p&gt;Let's be honest, managing hundreds of disconnected Kubernetes clusters is a nightmare at scale.&lt;/p&gt;

&lt;p&gt;GKE Hypercluster (now in private GA) tackles this head on by letting &lt;strong&gt;a single, Kubernetes-conformant GKE control plane manage 1 million chips across 256,000 nodes across multiple Google Cloud regions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What makes it stand out is the security model. It uses Google's &lt;strong&gt;Titanium Intelligence Enclave&lt;/strong&gt;, a software-hardened "no-admin-access" security engine. Your proprietary model weights and prompts stay cryptographically sealed from platform admins and infrastructure layers. That's a big deal for enterprise teams.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt; If you're running large-scale AI training across regions, you no longer have to deal with fragmented clusters. Your entire distributed infrastructure becomes one unified capacity reserve.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Supercharged Inference Performance: No More Months of Manual Tuning
&lt;/h2&gt;

&lt;p&gt;Getting to state-of-the-art (SOTA) inference used to take months of painful performance tuning. GKE is changing that with two solid updates:&lt;/p&gt;

&lt;h3&gt;
  
  
  ML-Driven Predictive Latency Boost
&lt;/h3&gt;

&lt;p&gt;The new feature inside &lt;strong&gt;GKE Inference Gateway&lt;/strong&gt; uses real-time capacity-aware routing to cut &lt;strong&gt;time-to-first-token (TTFT) latency by up to 70%&lt;/strong&gt;. No manual tuning needed. It just works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic KV Cache Storage Tiering
&lt;/h3&gt;

&lt;p&gt;Smart tiering across RAM, Local SSD, and GCS/Lustre helps with long-context memory bottlenecks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offloading to RAM: &lt;strong&gt;40%+ TTFT reduction&lt;/strong&gt; and 50% throughput gain (for 10K prompt length)&lt;/li&gt;
&lt;li&gt;Offloading to Local SSD: &lt;strong&gt;around 70% throughput improvement&lt;/strong&gt; (for 50K prompt length)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features are built on top of &lt;strong&gt;llm-d&lt;/strong&gt;, which just became an official CNCF Sandbox project. GKE also integrates with NVIDIA Dynamo for scaling large Mixture-of-Experts (MoE) models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt; You can go from deployment to frontier-grade inference in minutes instead of months. That's a huge deal.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Reinforcement Learning Enhancers: Stop Wasting GPU Time
&lt;/h2&gt;

&lt;p&gt;RL is one of the biggest drivers of AI compute demand right now. But the problem is that RL jobs involve a lot of sequential processing, which leaves GPUs and TPUs just sitting idle between steps.&lt;/p&gt;

&lt;p&gt;GKE is adding new native RL capabilities (currently in preview) to fix this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RL Scheduler&lt;/strong&gt; solves the "straggler effect" and inter-batch tail latency, keeping throughput high with intelligent routing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RL Sandbox&lt;/strong&gt; gives you kernel-level isolation for tool-calling and reward evaluation at millisecond-scale provisioning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RL Observability and Reliability dashboards&lt;/strong&gt; give you deep visibility out of the box to troubleshoot and optimize the whole RL loop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt; If you're doing RL training at scale, this is directly targeting the idle-time problem. Less idle time means lower costs. Simple as that.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Intent-Based Autoscaling: No More "Custom Metric Tax"
&lt;/h2&gt;

&lt;p&gt;Scaling AI workloads on anything beyond basic CPU or memory has always been painful. You'd need complex monitoring setups, IAM management, and a dependency on external observability stacks that could fail at the worst moment.&lt;/p&gt;

&lt;p&gt;GKE's new &lt;strong&gt;Intent-Based Autoscaling&lt;/strong&gt; brings native custom metrics support to the Horizontal Pod Autoscaler (HPA):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agentless architecture&lt;/strong&gt; pulls metrics directly from Pods, no external dependencies needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5x faster reaction time&lt;/strong&gt;, dropping from 25 seconds down to just 5 seconds&lt;/li&gt;
&lt;li&gt;If your external observability stack goes down, your autoscaling keeps running. No more cascade failures.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What this means for you:&lt;/strong&gt; This one flies under the radar but it's honestly one of the more impactful updates. Scaling on what actually matters for your workload, not just CPU, is now genuinely easy and reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Take: One Clear Pattern
&lt;/h2&gt;

&lt;p&gt;Looking at all five of these announcements together, there's a clear theme running through all of them: &lt;strong&gt;Google is making GKE the go-to platform for serious AI workloads&lt;/strong&gt;, not by piling on new features, but by removing the friction that's been slowing developers down.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent Sandbox removes the security-vs-performance tradeoff&lt;/li&gt;
&lt;li&gt;Hypercluster removes the cluster fragmentation headache&lt;/li&gt;
&lt;li&gt;Inference optimizations remove months of manual tuning&lt;/li&gt;
&lt;li&gt;RL Enhancers remove GPU idle waste&lt;/li&gt;
&lt;li&gt;Intent-based autoscaling removes fragile external metric dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every single update is about &lt;strong&gt;taking something painful away&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For anyone who's been frustrated running AI workloads on Kubernetes, the Next '26 GKE updates feel like Google finally saying: we get it, and here's the fix.&lt;/p&gt;

&lt;p&gt;Whether you're building multi-agent pipelines, serving frontier models, or doing RL training at scale, these updates are worth paying attention to, especially if cost and performance matter to you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What do you think about these GKE updates? Are you already using any of them or planning to? Drop a comment, I'd love to know what you're building!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cloudnextchallenge</category>
      <category>googlecloud</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Building Secure PDF Automation in .NET: The Trade-offs Nobody Talks About</title>
      <dc:creator>Kiell Tampubolon</dc:creator>
      <pubDate>Tue, 21 Apr 2026 14:44:40 +0000</pubDate>
      <link>https://forem.com/kielltampubolon/building-secure-pdf-automation-in-net-the-trade-offs-nobody-talks-about-f3c</link>
      <guid>https://forem.com/kielltampubolon/building-secure-pdf-automation-in-net-the-trade-offs-nobody-talks-about-f3c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Heads up: this article was originally published on Medium. I'm republishing it here for the Dev.to .NET community. Canonical link is set back to the original.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are building a backend service that generates thousands of PDFs daily. Invoices with payment details. Account statements with transaction histories. Internal reports with employee information. Your stakeholders want it fast, scalable, and automated. Your compliance team wants it secure, auditable, and locked down.&lt;/p&gt;

&lt;p&gt;Welcome to where developer convenience meets regulatory reality.&lt;/p&gt;

&lt;p&gt;Over the past year, I have worked on several projects involving automated document generation in regulated environments: financial services, healthcare systems, and internal enterprise platforms. IronPDF served as the rendering engine in these .NET systems, not because it solved security by itself, but because it integrated cleanly into architectures designed around secure data handling.&lt;/p&gt;

&lt;p&gt;This article walks through the practical trade-offs teams face when building PDF generation systems that handle sensitive data. Real patterns, real decisions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This is an engineering discussion based on real-world experience, not legal or compliance advice. Consult qualified counsel for regulatory requirements in your jurisdiction.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Composite Scenario
&lt;/h2&gt;

&lt;p&gt;Here is the kind of requirement set that keeps showing up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The business need:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate 10,000+ PDFs per day (invoices, statements, reports)&lt;/li&gt;
&lt;li&gt;Each document contains PII: names, addresses, account numbers&lt;/li&gt;
&lt;li&gt;Sub 2 second generation time per document&lt;/li&gt;
&lt;li&gt;Multiple templates and formats&lt;/li&gt;
&lt;li&gt;Bulk generation for batch processes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The regulatory reality:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data protection regulations apply (GDPR, CCPA, or similar)&lt;/li&gt;
&lt;li&gt;Financial data must be encrypted at rest and in transit&lt;/li&gt;
&lt;li&gt;Access to sensitive documents requires audit trails&lt;/li&gt;
&lt;li&gt;Data retention policies must be enforced&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The technical constraint:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limited infrastructure budget&lt;/li&gt;
&lt;li&gt;Small development team&lt;/li&gt;
&lt;li&gt;Tight delivery timelines&lt;/li&gt;
&lt;li&gt;Legacy system integration required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar? This is the reality for many teams building document automation today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 1: Data Access and Retrieval
&lt;/h2&gt;

&lt;p&gt;The first trade-off is speed against security granularity.&lt;/p&gt;

&lt;p&gt;Real-time fetch per PDF gives you maximum security and always-current data, but it slows generation and puts load on the database. A cached data pool is faster and more predictable, but data sitting in memory adds compliance complexity.&lt;/p&gt;

&lt;p&gt;Most teams end up with a hybrid:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Critical PII like SSNs and account numbers: always fetch fresh, never cache&lt;/li&gt;
&lt;li&gt;Semi-sensitive data like names and addresses: short-lived cache, 5 to 15 minutes&lt;/li&gt;
&lt;li&gt;Reference data: standard caching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The point is knowing which data warrants which treatment, and documenting those decisions for compliance reviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 2: Template and Rendering Logic
&lt;/h2&gt;

&lt;p&gt;Next trade-off: developer convenience against security boundaries.&lt;/p&gt;

&lt;p&gt;Tight coupling (data directly in templates) is quick to build and easy to modify, but templates often end up with access to more than they should actually display. Strict separation via ViewModels requires more upfront work and verbose code, but gives you clear data flow and makes audits easier.&lt;/p&gt;

&lt;p&gt;In practice, data projection before rendering works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified for clarity, production code needs additional error handling&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_invoiceRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Project to template-specific DTO&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;templateData&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;InvoiceTemplate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;InvoiceNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;CustomerName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MaskedAccountNumber&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;MaskAccountNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;invoice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccountNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Only include what the template actually needs&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RenderRazorViewToPdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"InvoiceTemplate.cshtml"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;templateData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you clear boundaries between data access and rendering, easier field-level security rules, and better audit trails.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 3: Document Security and Storage
&lt;/h2&gt;

&lt;p&gt;Trade-off here: performance against security depth.&lt;/p&gt;

&lt;p&gt;Plain PDFs with minimal security are fast to generate and retrieve, but anything that compromises storage exposes them directly. Maximum security with encryption and access control can be 3 to 5 times slower, plus key management complexity.&lt;/p&gt;

&lt;p&gt;A tiered model works better than one-size-fits-all:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tier 1: Highly sensitive (SSN, financial accounts)
├─ PDF password protection
├─ Encrypted storage
├─ Access logs per view
└─ Automatic expiration (30 to 90 days)

Tier 2: Moderately sensitive (invoices)
├─ Encrypted storage
├─ Authenticated access only
└─ Standard retention

Tier 3: Internal reports (aggregated data)
├─ Standard storage
└─ Basic access control
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;IronPDF makes password protection straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified, production needs proper key management&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;pdf&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RenderHtmlAsPdf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;htmlContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documentTier&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SecurityTier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HighlySensitive&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;GenerateSecurePassword&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecuritySettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowUserAnnotations&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SecuritySettings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AllowUserCopyPasteContent&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;SaveWithEncryption&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;storageKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not all documents need the same security level. Classify them and apply proportionate controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layer 4: Access Control and Delivery
&lt;/h2&gt;

&lt;p&gt;Final trade-off at the delivery layer: user convenience against audit completeness.&lt;/p&gt;

&lt;p&gt;Permissive delivery (direct links) means minimal logging, which is fast but leaves you with untracked sharing and compliance gaps. Strict delivery (authenticated per-access) gives you a complete audit trail but at the cost of slower UX and more infrastructure.&lt;/p&gt;

&lt;p&gt;Signed, time-limited URLs with access logging is usually the right balance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Simplified for clarity, production requires proper token validation&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;DocumentAccessToken&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GenerateAccessToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;documentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;TimeSpan&lt;/span&gt; &lt;span class="n"&gt;validity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_auditLog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogAccessRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DocumentAccessToken&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;DocumentId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;documentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;UserId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ExpiresAt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UtcNow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validity&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;Signature&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ComputeHMAC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;validity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Users can download within a time window. You get a proper audit trail. Sharing the link randomly does not grant indefinite access.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Trade-offs
&lt;/h2&gt;

&lt;p&gt;Beyond the obvious technical decisions, a few subtler trade-offs keep catching teams off guard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automation speed vs incident response
&lt;/h3&gt;

&lt;p&gt;Fast generation means fast mistakes. A data retrieval bug can expose thousands of documents before anyone notices.&lt;/p&gt;

&lt;p&gt;Build for recoverability from day one. Document versioning, batch rollback, sampling validation in production, embedded tracking metadata in PDFs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Crucial for identifying affected documents during incidents&lt;/span&gt;
&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MetaData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Subject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"Batch-&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;batchId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;pdf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MetaData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Keywords&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"DataVersion:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dataVersion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,Generated:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Simplicity vs long-term risk management
&lt;/h3&gt;

&lt;p&gt;"Just save PDFs to blob storage" seems simple until three years later when compliance asks: where is the data lineage, and how do you enforce deletion requests?&lt;/p&gt;

&lt;p&gt;Design metadata schema for future compliance needs from the start. Generation timestamp, data sources, requesting user, security classification, scheduled deletion date, related entity IDs for deletion cascades.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security theater vs real risk
&lt;/h3&gt;

&lt;p&gt;Adding controls that look good on paper does not prevent logic bugs that expose PII.&lt;/p&gt;

&lt;p&gt;Focus security effort where risks actually live:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated tests for PII leakage in templates&lt;/li&gt;
&lt;li&gt;Code review on data access patterns&lt;/li&gt;
&lt;li&gt;Monitoring for anomalous generation volumes&lt;/li&gt;
&lt;li&gt;Developer security training&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make secure coding the path of least resistance, not an obstacle course.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Decision Framework
&lt;/h2&gt;

&lt;p&gt;When you are stuck on a trade-off call, a simple framework helps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Classify document risk&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Risk = (Data Sensitivity) x (Access Scope) x (Retention Period)

High risk (&amp;gt;7): Financial accounts, medical PHI, SSN
Medium risk (4 to 7): Customer invoices, internal reports
Low risk (&amp;lt;4): Public reports, marketing materials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Map trade-offs to risk&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High risk: accept slower generation, implement per-document access control&lt;/li&gt;
&lt;li&gt;Low risk: optimize for speed, use simple authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Document the decision&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Decision: Cache customer names for batch generation
Risk: Medium
Rationale: Names alone aren't highly sensitive. A 15-minute cache
           significantly improves batch performance.
Mitigations: Cache encryption, automatic invalidation.
Review: Q3 2026
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of decision log pays off during compliance reviews and team onboarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons From the Trenches
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Perfect security is the enemy of good security.&lt;/strong&gt; Teams that try to implement every best practice end up with systems so complex nobody understands them, which leads to developer workarounds that bypass security entirely. Proportionate security based on actual risk, then iterate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance debt compounds faster than technical debt.&lt;/strong&gt; That quick hack to meet a deadline does not just slow down development. It creates regulatory risk, potential fines, and legal liability. Treat security decisions as first-class architectural concerns from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Observability is security.&lt;/strong&gt; You cannot secure what you cannot see. Monitor document generation volume anomalies, failed access attempts, unusual document sizes, generation time spikes, and access pattern anomalies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clear mental models enable secure development.&lt;/strong&gt; Developers make secure decisions when they understand what data is sensitive, where security boundaries exist, and how to implement controls correctly. Invest in training and documentation, not just tools and processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementation Checklist
&lt;/h2&gt;

&lt;p&gt;Based on real project learnings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Foundation (Week 1 to 2)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Document classification and security requirements mapped&lt;/li&gt;
&lt;li&gt;[ ] Data access patterns and template strategy documented&lt;/li&gt;
&lt;li&gt;[ ] Storage encryption approach selected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Core implementation (Week 3 to 6)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] PDF rendering with proper error handling&lt;/li&gt;
&lt;li&gt;[ ] Data projection layer (no direct entity access)&lt;/li&gt;
&lt;li&gt;[ ] Document metadata schema and basic access control&lt;/li&gt;
&lt;li&gt;[ ] Generation monitoring and logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security and production (Week 7 to 10)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Password protection and time-limited access tokens&lt;/li&gt;
&lt;li&gt;[ ] Audit logging and deletion workflows&lt;/li&gt;
&lt;li&gt;[ ] Security testing and performance validation&lt;/li&gt;
&lt;li&gt;[ ] Incident response procedures and monitoring dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Building document automation for sensitive data is fundamentally about making smart trade-offs. There is no perfect solution. Only solutions that fit your specific context, risk profile, and constraints.&lt;/p&gt;

&lt;p&gt;Teams that succeed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Acknowledge trade-offs explicitly rather than pretending they do not exist&lt;/li&gt;
&lt;li&gt;Make decisions proportionate to actual risk&lt;/li&gt;
&lt;li&gt;Document reasoning for future teams and compliance reviews&lt;/li&gt;
&lt;li&gt;Build for evolution, knowing requirements will change&lt;/li&gt;
&lt;li&gt;Focus on developer experience, because secure systems need developer buy-in&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PDF libraries like IronPDF provide the building blocks. The architecture, the trade-offs, and the decisions are on us.&lt;/p&gt;

&lt;p&gt;The goal is not perfection. It is building systems that are good enough to trust, simple enough to maintain, and flexible enough to evolve as regulations, threats, and business needs change.&lt;/p&gt;




&lt;p&gt;If you are building secure document automation systems, I would love to hear what trade-offs you have encountered. Especially decisions that worked differently in your context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Originally published on &lt;a href="https://medium.com/the-constellar-digital-technology-blog/when-secure-data-meets-document-automation-a-real-world-case-study-022ffde7956c" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>security</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
