<?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>DEV Community: Eric Rodríguez</title>
    <description>The latest articles on DEV Community by Eric Rodríguez (@ericrodriguez10).</description>
    <link>https://dev.to/ericrodriguez10</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%2F3677578%2Fcebf54ee-c6c0-436d-8570-7412b62d4321.jpeg</url>
      <title>DEV Community: Eric Rodríguez</title>
      <link>https://dev.to/ericrodriguez10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ericrodriguez10"/>
    <language>en</language>
    <item>
      <title>Day 94: Stop using .pem for Apple Push Notifications. Do this instead.</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Fri, 29 May 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-94-stop-using-pem-for-apple-push-notifications-do-this-instead-40el</link>
      <guid>https://dev.to/ericrodriguez10/day-94-stop-using-pem-for-apple-push-notifications-do-this-instead-40el</guid>
      <description>&lt;p&gt;Today, I built the push notification engine for my Serverless AI Financial Agent. The goal was simple: if a user spends &amp;gt;100 EUR in a day, hit their iPhone with an alert and update their Home Screen widget.&lt;/p&gt;

&lt;p&gt;Getting AWS Lambda to talk to APNs (Apple Push Notification service) requires authorization.&lt;/p&gt;

&lt;p&gt;The Mistake You Are Probably Making:&lt;br&gt;
Generating a .pem certificate in the Apple Developer Portal. These expire every year, requiring manual intervention, and they force you to manage separate certs for Sandbox and Prod.&lt;/p&gt;

&lt;p&gt;The Architecture Fix:&lt;br&gt;
Use Token-Based Authentication (.p8).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate a .p8 Auth Key in the Apple Developer portal. It is Team-Scoped and never expires.&lt;/li&gt;
&lt;li&gt;Go to AWS SNS -&amp;gt; Push notifications.&lt;/li&gt;
&lt;li&gt;Create a Platform Application (Apple iOS/VoIP/Mac).&lt;/li&gt;
&lt;li&gt;Choose Token for authentication (not Certificate).&lt;/li&gt;
&lt;li&gt;Paste your Key ID, Team ID, Bundle ID, and the .p8 file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, your AWS Lambda doesn't need to struggle with APNs connections. It just fires an event:&lt;/p&gt;

&lt;h1&gt;
  
  
  Lambda just publishes to SNS. SNS handles Apple.
&lt;/h1&gt;

&lt;p&gt;sns.publish(&lt;br&gt;
    TargetArn=os.environ['APNS_SANDBOX_PLATFORM_APPLICATION_ARN'],&lt;br&gt;
    Message=json.dumps(apns_payload),&lt;br&gt;
    MessageStructure='json'&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;Widget Syncing Issue:&lt;br&gt;
iOS heavily sandboxes processes. If your app receives the push notification, your Widget cannot read the new data.&lt;br&gt;
To fix this, you must configure an App Group (e.g., group.com.yourcompany.app). This creates a shared memory space. The main app receives the SNS push, writes the new spending limit to the App Group's UserDefaults, and the Widget reloads its timeline reading from that exact same shared space.&lt;br&gt;
Stop managing certificates. Start building scalable infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8pa4hbtgsijk48nfzsv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8pa4hbtgsijk48nfzsv.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ios</category>
      <category>serverless</category>
      <category>swift</category>
    </item>
    <item>
      <title>Day 93: Bridging React to iOS Widgets and Face ID</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Thu, 28 May 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-93-bridging-react-to-ios-widgets-and-face-id-40b1</link>
      <guid>https://dev.to/ericrodriguez10/day-93-bridging-react-to-ios-widgets-and-face-id-40b1</guid>
      <description>&lt;p&gt;Taking a web app to mobile isn't just about making it responsive. It's about tapping into the OS.&lt;/p&gt;

&lt;p&gt;Today, I expanded the native iOS capabilities of my Serverless Financial Agent using Capacitor.&lt;/p&gt;

&lt;p&gt;The Auth Flow: Face ID + PIN&lt;br&gt;
Relying solely on AWS Cognito for every app open is slow and ruins the mobile experience. I already had a local PIN system, but typing a PIN is tedious.&lt;/p&gt;

&lt;p&gt;I integrated the NativeBiometricAuthPlugin to trigger Face ID. If Face ID succeeds, the local session unlocks. If it fails (or the user cancels), it seamlessly falls back to the local PIN. Zero-trust security without the friction.&lt;/p&gt;

&lt;p&gt;The Data Flow: React to WidgetKit&lt;br&gt;
I wanted my users to see their "Spending Overview" directly on their iOS Home Screen.&lt;/p&gt;

&lt;p&gt;The challenge? React (running in a WebView via Capacitor) cannot talk to an iOS Widget (written in Swift).&lt;/p&gt;

&lt;p&gt;The solution was an Apple App Group.&lt;br&gt;
I created a shared directory: group.com.quiklygroup.duromoney.&lt;br&gt;
I built a custom native plugin. When my React app receives new financial data from my AWS Lambda backend, it sends a snapshot to the plugin, which writes it to the App Group. The native iOS widget then reads that snapshot and updates the Home Screen.&lt;/p&gt;

&lt;p&gt;The Permission Strategy&lt;br&gt;
I also restructured the onboarding. I intentionally delay asking for Push Notification and Face ID permissions until after the user has logged in and seen their financial dashboard. If you ask for permissions before showing value, users will deny them.&lt;/p&gt;

&lt;p&gt;Build the backend for scale, but design the frontend for humans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwd0yoiwha1e3uc7li6k7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwd0yoiwha1e3uc7li6k7.jpeg" alt=" " width="800" height="1660"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ios</category>
      <category>react</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Day 92: Moving to iOS and the Apple Push Notification roadblock</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Wed, 27 May 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-92-moving-to-ios-and-the-apple-push-notification-roadblock-50ek</link>
      <guid>https://dev.to/ericrodriguez10/day-92-moving-to-ios-and-the-apple-push-notification-roadblock-50ek</guid>
      <description>&lt;p&gt;Taking a cloud-native web app to mobile introduces a whole new set of architectural challenges.&lt;/p&gt;

&lt;p&gt;Today, I wrapped my React SPA into a native iOS app using Capacitor. The goal was to maintain a single codebase communicating with my AWS Lambda backend while gaining access to native device features.&lt;/p&gt;

&lt;p&gt;The Auth Fix: Deep Links&lt;br&gt;
Authentication is notoriously tricky when moving from Web to Mobile. I use AWS Cognito for OAuth (Google Sign-In). On mobile, when the browser finishes the auth flow, it needs to know how to return to the app.&lt;/p&gt;

&lt;p&gt;I had to configure the iOS App.xcworkspace to accept custom URL schemes and update my Cognito App Client to accept duromoney://localhost as a valid callback URL. Without this, users log in and get stuck staring at a blank Safari screen.&lt;/p&gt;

&lt;p&gt;The FinOps Dilemma: SMS vs. Push&lt;br&gt;
Right now, my AI agent sends "High Spending" alerts via SMS using Amazon SNS. SMS costs money. Push notifications don't.&lt;/p&gt;

&lt;p&gt;I wrote the backend logic to register the device token and push alerts via APNs (Apple Push Notification service) alongside the SMS so I could compare latency.&lt;/p&gt;

&lt;p&gt;The Roadblock&lt;br&gt;
I hit a hard wall. Xcode refused to build, throwing:&lt;br&gt;
Personal development teams do not support the Push Notifications capability.&lt;/p&gt;

&lt;p&gt;AWS lets you build multi-region serverless architectures for pennies. Apple won't even let you send a local test Push Notification to your own device unless you pay the $99/year Apple Developer Program fee.&lt;/p&gt;

&lt;p&gt;The Fix for Now: I'm keeping the SMS fallback active. Once the paid Apple Developer account is active, I will extract the .p8 Auth Key, Team ID, and Bundle ID to create an APNS_SANDBOX Platform Application in AWS SNS and finally bypass the SMS costs.&lt;/p&gt;

&lt;p&gt;Cloud providers give you the tools. Mobile platforms sell you the keys!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgh4j4lsjktxy0uwprvb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpgh4j4lsjktxy0uwprvb.jpeg" alt=" " width="800" height="1657"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ios</category>
      <category>react</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Day 91: Why I stopped using GenAI for budgeting math</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Tue, 26 May 2026 13:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-91-why-i-stopped-using-genai-for-budgeting-math-1d4k</link>
      <guid>https://dev.to/ericrodriguez10/day-91-why-i-stopped-using-genai-for-budgeting-math-1d4k</guid>
      <description>&lt;p&gt;When building AI-powered apps, you have to know when to turn the AI off.&lt;/p&gt;

&lt;p&gt;Today, I was testing my Serverless Financial Agent. I asked it a simple question: "How much can I spend today without breaking my goal?"&lt;/p&gt;

&lt;p&gt;The Amazon Bedrock LLM gave me a beautifully written, highly confident answer. The only problem? The math was completely hallucinated.&lt;/p&gt;

&lt;p&gt;The Problem: LLMs predict the next best word; they don't do arithmetic. If you let GenAI calculate daily limits based on raw transaction data, it will eventually confidently authorize spending that bankrupts your user.&lt;/p&gt;

&lt;p&gt;The Fix: I added a deterministic interceptor in my AWS Lambda backend.&lt;/p&gt;

&lt;p&gt;Instead of passing the prompt directly to the AI, my Python router now uses regex to catch specific intents. If the user asks about their daily limit, Python takes over:&lt;/p&gt;

&lt;h1&gt;
  
  
  Deterministic Math &amp;gt; AI Hallucinations
&lt;/h1&gt;

&lt;p&gt;safe_daily_limit = (recorded_monthly_income / days_in_month) - daily_savings_goal&lt;/p&gt;

&lt;p&gt;If the system detects 0 recorded income for the month, it hard-stops and refuses to calculate a limit. The AI is only used to format the final delivery in its designated "tough love" persona, but the underlying numbers are strictly governed by standard code.&lt;/p&gt;

&lt;p&gt;I also decoupled my public landing page from my authenticated React SPA.&lt;br&gt;
If you want to use Google OAuth in your app, GCP requires publicly accessible /privacy and /terms pages. By splitting the routing, unauthenticated users hit a lightning-fast static landing page cached by AWS CloudFront, while authenticated users get routed directly to the heavy dashboard.&lt;/p&gt;

&lt;p&gt;Route language to the LLM. Route math to Python. Code for intelligence, but architect for accuracy!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8er8g39aeczs8qbw1xg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8er8g39aeczs8qbw1xg.png" alt=" " width="799" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>react</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Day 90: Building a Resilient App Shell &amp; Theme Engine in React</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Mon, 25 May 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-90-building-a-resilient-app-shell-theme-engine-in-react-27oc</link>
      <guid>https://dev.to/ericrodriguez10/day-90-building-a-resilient-app-shell-theme-engine-in-react-27oc</guid>
      <description>&lt;p&gt;A robust serverless backend is useless if your frontend feels like an unfinished prototype. Today, I executed a complete visual and structural redesign of my Financial Agent.&lt;/p&gt;

&lt;p&gt;Here are the technical highlights of the frontend overhaul:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Full Theme Persistence&lt;br&gt;
I built a theme engine supporting System, Light, and Black modes using #171717 and #f4f5f0 base colors. Instead of just keeping this state in the browser, the React app sends the appearance_preference to the AWS backend. This ensures cross-device UI continuity when the user authenticates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;App Shell Architecture&lt;br&gt;
I ripped out the top-bar navigation and implemented a proper desktop App Shell. It features a sticky left sidebar and a dedicated right insights panel for desktop. To fix native scrolling physics, I applied overscroll-behavior: none to the body, preventing the browser's default background rubber-banding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hardening the Local App Lock&lt;br&gt;
The PIN lock screen got a UX and security upgrade. I added an invisible input over the PIN dots to seamlessly trigger the mobile keyboard. Architecturally, I implemented a custom PBKDF2 fallback for environments where the native crypto.subtle API is blocked, and wired up a backend endpoint for server-side PIN verification.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Structure your UI with the same rigor you apply to your databases.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y5g1lxz7gialmn52srh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8y5g1lxz7gialmn52srh.png" alt=" " width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>ui</category>
      <category>aws</category>
      <category>saas</category>
    </item>
    <item>
      <title>Day 89: Building a Savings Dashboard &amp; Reusing AI Responses (FinOps)</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Sat, 23 May 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-89-building-a-savings-dashboard-reusing-ai-responses-finops-5hd</link>
      <guid>https://dev.to/ericrodriguez10/day-89-building-a-savings-dashboard-reusing-ai-responses-finops-5hd</guid>
      <description>&lt;p&gt;Adding features to an AI-powered SaaS is easy. Doing it without increasing your LLM token consumption is the real architectural challenge.&lt;/p&gt;

&lt;p&gt;Today, I replaced the "Transactions" navigation tab with a dedicated "Savings" view in my Serverless Financial Agent. I moved existing gamification widgets there and built a new Daily Savings chart using Recharts to visualize the user's daily pacing against their target goals.&lt;/p&gt;

&lt;p&gt;The biggest win was the FinOps strategy. The new dashboard needed a financial recommendation. Instead of triggering a new, expensive Amazon Nova prompt, I decided to recycle data.&lt;/p&gt;

&lt;p&gt;Every morning, my AWS Lambda generates a daily report email containing a financial "Advice" section. I modified the backend to extract that exact block of text and persist it in the user's DynamoDB profile as latest_daily_savings_advice.&lt;/p&gt;

&lt;p&gt;Now, when the React frontend loads the Savings view, it simply fetches that cached string instead of pinging the AI. If there isn't enough signal, it defaults to a deterministic math calculation. By decoupling the AI generation from the UI rendering, I expanded the product's capabilities while keeping the marginal cost at exactly zero.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm8av1ye1mhklyn4vt8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhm8av1ye1mhklyn4vt8n.png" alt=" " width="799" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>react</category>
      <category>finops</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Day 88: Architecting a Serverless Monetization Engine (DynamoDB &amp; Affiliate APIs)</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Fri, 22 May 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-88-architecting-a-serverless-monetization-engine-dynamodb-affiliate-apis-13g9</link>
      <guid>https://dev.to/ericrodriguez10/day-88-architecting-a-serverless-monetization-engine-dynamodb-affiliate-apis-13g9</guid>
      <description>&lt;p&gt;Building a cloud application is fun until you get the AWS bill. To make my Serverless Financial Agent sustainable, I started building a contextual Monetization Engine today by applying to strict Fintech affiliate networks (financeAds and AdCredy).&lt;/p&gt;

&lt;p&gt;Getting approved by these networks is hard if you just have a static site. But when you explain that your traffic sits behind an AWS Cognito login and uses an AI model to evaluate real-time API banking data, you become a premium publisher.&lt;/p&gt;

&lt;p&gt;The Architecture of Affiliate Links:&lt;br&gt;
Never hardcode affiliate links in your frontend code. If a campaign pauses, your app breaks, and you have to trigger a full CI/CD pipeline just to swap a URL.&lt;/p&gt;

&lt;p&gt;Instead, I am designing a database-driven approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Storage: A new FinanceAgent-Offers table in DynamoDB will hold the offer_id, affiliate_url, and category.&lt;/li&gt;
&lt;li&gt;Logic: My Python Lambda function calculates the user's financial score. If they are broke, it pulls a credit offer from the DB. If they are saving well, it pulls an investment broker offer.&lt;/li&gt;
&lt;li&gt;Delivery: The React app just receives a clean JSON array and renders the UI cards dynamically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Monetization should be treated as a backend microservice, entirely decoupled from your frontend presentation layer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpstpdl8kqdg3oztw5xa7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpstpdl8kqdg3oztw5xa7.png" alt=" " width="799" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>saas</category>
      <category>architecture</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Day 87: Voice-Interactive AI with Amazon Polly &amp; DynamoDB Caching</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Thu, 21 May 2026 14:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-87-voice-interactive-ai-with-amazon-polly-dynamodb-caching-jdg</link>
      <guid>https://dev.to/ericrodriguez10/day-87-voice-interactive-ai-with-amazon-polly-dynamodb-caching-jdg</guid>
      <description>&lt;p&gt;Imagine asking your app directly, "What was my biggest expense this month?" and having it instantly reply aloud, scolding you like a ruthless personal financial coach.&lt;/p&gt;

&lt;p&gt;Today, I built a Voice Interaction loop into my Serverless Financial Agent. The architecture mixes native web APIs with AWS machine learning services, bound together by strict cost controls.&lt;/p&gt;

&lt;p&gt;The Audio Pipeline&lt;br&gt;
For input, I used the native browser SpeechRecognition API. It's completely free and captures the user's voice, submitting the form automatically upon silence.&lt;br&gt;
For output, the Python Lambda calls Amazon Polly to synthesize the AI's response using high-fidelity Neural voices.&lt;/p&gt;

&lt;p&gt;FinOps: The Caching Layer&lt;br&gt;
Amazon Polly can get expensive if abused. I built a caching mechanism in DynamoDB (FinanceAgent-Cache). Every time text is synthesized, the Base64 MP3 is saved with a SHA-256 hash of the text and language. If the same response needs to be read again, the backend serves the cached audio instead of calling Polly.&lt;/p&gt;

&lt;p&gt;Backend Gating &amp;amp; IAM&lt;br&gt;
I didn't just hide the microphone button in the UI. I secured the backend route (?action=synthesize_voice) to strictly reject any requests that don't match specific premium user emails verified via Cognito JWTs. Finally, I locked down the Lambda execution role with a single inline policy: polly:SynthesizeSpeech.&lt;/p&gt;

&lt;p&gt;Voice AI is a fantastic feature, but caching and access control are what make it production-ready.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gplhxy00f5p8ytwg54o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7gplhxy00f5p8ytwg54o.png" alt=" " width="799" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>react</category>
      <category>serverless</category>
      <category>python</category>
    </item>
    <item>
      <title>Day 86: Adding Multi-Language Support with AI Translation Caching</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Wed, 20 May 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-86-adding-multi-language-support-with-ai-translation-caching-29f3</link>
      <guid>https://dev.to/ericrodriguez10/day-86-adding-multi-language-support-with-ai-translation-caching-29f3</guid>
      <description>&lt;p&gt;Translating a static React app is easy. Translating a dynamic AI agent without draining your cloud budget requires architectural discipline.&lt;/p&gt;

&lt;p&gt;Today, I added support for 5 languages (en, es, fr, de, it) to my Serverless Financial Agent.&lt;/p&gt;

&lt;p&gt;The biggest risk was cost. If a user toggles the language dropdown, asking the LLM to regenerate the entire financial analysis is a waste of money.&lt;/p&gt;

&lt;p&gt;To fix this, I built a specific POST ?action=translate_message endpoint. It translates the currently visible AI string once and caches it in DynamoDB (FinanceAgent-Cache) using a SHA-256 hash of the language and text. Subsequent language toggles hit the NoSQL cache (cache_hit: true) instead of Amazon Nova, dropping the translation cost to zero.&lt;/p&gt;

&lt;p&gt;For scheduled tasks like daily SMS alerts and email reports, the backend simply reads the user's preferred_language from DynamoDB and generates the text natively during its normal run.&lt;/p&gt;

&lt;p&gt;Lesson learned: When scaling AI globally, caching is your best financial defense.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m1a2j8siyyfsk3nnnzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m1a2j8siyyfsk3nnnzd.png" alt=" " width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>react</category>
      <category>serverless</category>
      <category>finops</category>
    </item>
    <item>
      <title>Day 85: Building a Secure App Lock in React with PBKDF2</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Tue, 19 May 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-85-building-a-secure-app-lock-in-react-with-pbkdf2-3ca1</link>
      <guid>https://dev.to/ericrodriguez10/day-85-building-a-secure-app-lock-in-react-with-pbkdf2-3ca1</guid>
      <description>&lt;p&gt;Authentication gets you into the application, but what happens when a user leaves their laptop open? When building financial tools, an unattended screen is a critical vulnerability.&lt;/p&gt;

&lt;p&gt;Today, I added a Local App Lock to my Serverless Financial Agent. While AWS Cognito handles the primary session, this new layer acts as a local inactivity shield.&lt;/p&gt;

&lt;p&gt;The Cryptography Layer&lt;br&gt;
A 4-digit PIN is easy to brute-force if stored poorly. I ensured the PIN is never saved in plain text. Instead, I used the native Web Crypto API. The application generates a random salt and hashes the PIN using the PBKDF2 algorithm with SHA-256. Only pinHash and pinSalt live in localStorage, keeping the device secure.&lt;/p&gt;

&lt;p&gt;Idle Detection&lt;br&gt;
I built an event listener hook that tracks pointer movements, key presses, and touch events. If the user is inactive for 10 minutes, the financial dashboard is immediately obscured by the lock screen. It also tracks the visibilitychange event, measuring the exact elapsed time when the tab is running in the background.&lt;/p&gt;

&lt;p&gt;The "Forgot PIN" Failsafe&lt;br&gt;
If a user forgets their local PIN, there is no simple "reset link." For maximum security, clicking "Forgot PIN" instantly clears the local App Lock state and executes a hard sign-out via the AWS Amplify SDK. The user must fully re-authenticate with their Cognito credentials and create a brand new PIN from scratch.&lt;/p&gt;

&lt;p&gt;Frontend security is about defense in depth. Never trust local storage with plain text secrets, even if it is just a simple 4-digit PIN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob4td1xi94j32oay12zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob4td1xi94j32oay12zg.png" alt=" " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>security</category>
      <category>javascript</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Day 84: Merging Cognito Identities &amp; Surviving a 502 Gateway Error</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Mon, 18 May 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-84-merging-cognito-identities-surviving-a-502-gateway-error-3hb5</link>
      <guid>https://dev.to/ericrodriguez10/day-84-merging-cognito-identities-surviving-a-502-gateway-error-3hb5</guid>
      <description>&lt;p&gt;Today I almost broke my serverless production environment, but AWS disaster recovery features saved the day.&lt;/p&gt;

&lt;p&gt;I was deploying a major update to my Financial Agent to fix a split identity issue. Users logging in with Email/Password and Google OAuth were getting separate DynamoDB partitions. I rewrote the backend to unify the identity resolution around the verified email address.&lt;/p&gt;

&lt;p&gt;At the same time, I was updating the transaction classification logic. The system needed to strictly separate refunds/credits from actual income so the AI wouldn't hallucinate false financial praise.&lt;/p&gt;

&lt;p&gt;The Deployment Incident:&lt;br&gt;
I deployed the new Python code to AWS Lambda, but I forgot to package a newly required module in the deployment zip. The immediate result was a global 502 Bad Gateway. While trying to patch it quickly, I caused a 500 Internal Server Error by calling an unimported configuration variable.&lt;/p&gt;

&lt;p&gt;The Rollback:&lt;br&gt;
Because I treat my serverless infrastructure seriously, I had taken two precautions before deploying:&lt;/p&gt;

&lt;p&gt;I created DynamoDB On-Demand backups for my Cache, Memory, and Transactions tables.&lt;/p&gt;

&lt;p&gt;I published numbered versions of my Lambda function instead of just overwriting $LATEST.&lt;/p&gt;

&lt;p&gt;Instead of panicking and writing hotfixes in the AWS Console, I simply rolled back the API Gateway to point to Lambda Version 1. The system stabilized instantly. I then fixed my local code, bundled the dependencies correctly, and deployed Version 4 cleanly.&lt;/p&gt;

&lt;p&gt;The lesson here is simple: Never deploy major logic changes without database backups and function versioning. Rollbacks should be a one-click operation, not a debugging session.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvkbf3yisrv5xe54cim0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvkbf3yisrv5xe54cim0.png" alt=" " width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>serverless</category>
      <category>fintech</category>
    </item>
    <item>
      <title>Day 83: AWS SNS SMS Alerts &amp; Segment Cost Optimization</title>
      <dc:creator>Eric Rodríguez</dc:creator>
      <pubDate>Fri, 15 May 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ericrodriguez10/day-83-aws-sns-sms-alerts-segment-cost-optimization-1e6d</link>
      <guid>https://dev.to/ericrodriguez10/day-83-aws-sns-sms-alerts-segment-cost-optimization-1e6d</guid>
      <description>&lt;p&gt;Adding SMS alerts to your serverless application is incredibly easy with AWS SNS. Keeping those alerts cheap, however, requires a bit of FinOps knowledge.&lt;/p&gt;

&lt;p&gt;Today, I restored the SMS alerting feature for my Serverless Financial Agent. If a user spends more than 100€ in a day, the system sends them a harsh financial reality check via text.&lt;/p&gt;

&lt;p&gt;Here are the critical architectural updates I made to secure the pipeline and optimize costs:&lt;/p&gt;

&lt;p&gt;The ASCII-Only Rule&lt;br&gt;
Initially, the AI included emojis in the SMS text. This was a costly mistake. Emojis force the message into UCS-2 encoding, shrinking the SMS segment limit from 160 characters to just 70. By refactoring the Python logic to use ASCII-only rotating phrases, I avoided multi-segment billing charges entirely.&lt;/p&gt;

&lt;p&gt;Strict IAM Policies&lt;br&gt;
I removed any broad SNS permissions from the Lambda execution role. Instead, I attached a granular inline policy: FinanceAgentSmsPublish. This ensures the Lambda only has the sns:Publish action allowed.&lt;/p&gt;

&lt;p&gt;Account-Level Guardrails&lt;br&gt;
AWS SNS can get expensive if a bug causes an infinite loop of messages. I configured the SNS MonthlySpendLimit attribute to a strict $1 limit while operating in the SNS Sandbox environment.&lt;/p&gt;

&lt;p&gt;The Lesson: When writing cloud-native code, you must treat your cloud bill as an architectural constraint. Optimize your payload encoding and always lock down your IAM roles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdrxj8asepab8mq4chko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdrxj8asepab8mq4chko.png" alt=" " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>serverless</category>
      <category>fintec</category>
    </item>
  </channel>
</rss>
