<?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: Asuka Suehiro</title>
    <description>The latest articles on Forem by Asuka Suehiro (@kskiii).</description>
    <link>https://forem.com/kskiii</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%2F3668156%2F865d8631-5a32-49b0-b535-20f3ac6a76af.jpeg</url>
      <title>Forem: Asuka Suehiro</title>
      <link>https://forem.com/kskiii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kskiii"/>
    <language>en</language>
    <item>
      <title>Designing Around External API Assumptions: A Lesson from a Free Exchange Rate API</title>
      <dc:creator>Asuka Suehiro</dc:creator>
      <pubDate>Fri, 02 Jan 2026 01:01:23 +0000</pubDate>
      <link>https://forem.com/kskiii/designing-around-external-api-assumptions-a-lesson-from-a-free-exchange-rate-api-38jn</link>
      <guid>https://forem.com/kskiii/designing-around-external-api-assumptions-a-lesson-from-a-free-exchange-rate-api-38jn</guid>
      <description>&lt;p&gt;I developed and deployed an application called YenUp, which compares today's exchange rate with yesterday's and sends a notification based on the result. To keep the project simple and free, I used the Frankfurter API as the data source.&lt;/p&gt;

&lt;p&gt;I was happy to have completed it. However, I soon noticed something wrong with the notification I received. &lt;/p&gt;

&lt;p&gt;It was supposed to notify me when today's rate is better than yesterday's. To debug the delivery pipeline end-to-end, I added a &lt;code&gt;notification=true&lt;/code&gt; flag that forces a Slack message even when the rate doesn’t change.&lt;br&gt;
What I actually received looked like this:&lt;br&gt;
&lt;code&gt;Test Notification (forced). CAD/JPY: Yesterday 114.4300 -&amp;gt; Today 114.4300&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At first, I suspected a bug in my own implementation. I reviewed the logic and double-checked the comparison code. Eventually, I realized that the issue was not in my code, but in my assumption about the API.&lt;/p&gt;

&lt;p&gt;This behavior was further amplified by my own fallback logic.&lt;br&gt;
When data for a specific date was unavailable (for example, on weekends or before the daily update), my implementation fell back to the &lt;code&gt;latest&lt;/code&gt; endpoint.&lt;br&gt;
As a result, non-business days could effectively collapse into the same underlying rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;This experience made me realize that the real problem was not the API behavior itself, but my assumption about it.&lt;br&gt;
I had designed the logic assuming that "today" and "yesterday" were calendar days. However, external APIs often define these terms based on their own business rules, which might not align with how a product expects to use the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'll do next
&lt;/h2&gt;

&lt;p&gt;Based on this, I'm considering changing the comparison logic to use business days instead of calendar days.&lt;br&gt;
I haven't fully implemented this yet, mainly because defining business days consistently across currencies introduces additional complexity.&lt;/p&gt;

&lt;p&gt;This small bug led me to question my assumptions, which changed how I think about external APIs and business rules. I hope to continue learning through future projects.&lt;/p&gt;

</description>
      <category>api</category>
    </item>
    <item>
      <title>Automating Go App Deployment to Google Cloud Run with GitHub Actions(Free Tier)</title>
      <dc:creator>Asuka Suehiro</dc:creator>
      <pubDate>Sat, 20 Dec 2025 00:40:52 +0000</pubDate>
      <link>https://forem.com/kskiii/automating-go-app-deployment-to-google-cloud-run-with-github-actionsfree-tier-4995</link>
      <guid>https://forem.com/kskiii/automating-go-app-deployment-to-google-cloud-run-with-github-actionsfree-tier-4995</guid>
      <description>&lt;p&gt;Hi, everyone! This is my first article on dev.to.👋 &lt;br&gt;
I recently built a &lt;strong&gt;Go application&lt;/strong&gt; and deployed it, using &lt;strong&gt;Google Cloud Run&lt;/strong&gt; and &lt;strong&gt;GitHub Actions&lt;/strong&gt; to deepen my DevOps skills. In this post, I'll share how I automated the deployment process and what I learned along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background
&lt;/h3&gt;

&lt;p&gt;I currently live in Canada but earn my salary in JPY. Since the exchange rate fluctuates constantly, checking the CAD/JPY rate manually every day has been a hassle. I wanted a system that would automatically notify me via Slack whenever the rate improved compared to the day before. To achieve this, I decided to autmate the workflow, using GCP and GitHub Actions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The System Architechture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;graph LR
  GitHub[GitHub] --&amp;gt; Actions[GitHub Actions]
  Actions --&amp;gt; Registry[Artifact Registry]
  Registry --&amp;gt; CloudRun[Cloud Run]
  Scheduler[Cloud Scheduler] --&amp;gt; CloudRun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why these technologies?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Why Go?: It's a static typed language, which ensures robustness and keep the container image size small.&lt;/li&gt;
&lt;li&gt;Why Google Cloud Run?: It's a serverless platform, so I don't need to manage severs. Plus, it scales to zero when not in use, allowing me to run this bot within the &lt;strong&gt;Free Tier&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Why GitHub Actions?: It allows me to manage CI/CD pipeline at right next to my code. Integrating it with GCP is secure and seamless.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Challenges &amp;amp; Solutions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The "Secure by Default" Trap (403 Forbidden)&lt;/strong&gt;: At first, I didn't realize that Google Cloud Run blocks unauthenticated access by default and focused on &lt;code&gt;403 Forbidden&lt;/code&gt; errors without allowing unauthenticated invocations. I set OIDC Token in Cloud Scheduler Authentication Header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD Configuration Details&lt;/strong&gt;: I spent Time debugging The GitHub Actions pipeline because of a simple mismatch in the Artifact Registry configuration. I confused the Repository Name with the Repository ID. This experience taught me that in DevOps, paying attention to the smallest details in variable names is just as important as writing the code itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What I Learned
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Trade-off: Initial Setup Pain vs. Future Efficiency### Future Improvements&lt;/strong&gt;&lt;br&gt;
Runnning code locally is intuitive and instant, while moving to the cloud felt tedious. But once I overcame that initial barrier, I realized the power of automation. The system now works for me, while I sleep. I learned that engineering is about &lt;strong&gt;enduring the initial struggle of setup to achieve long-term efficiency&lt;/strong&gt;. This project allows me to save time to do something else to improve my skill - which I believe is the essence of technological progress.&lt;/p&gt;

&lt;h3&gt;
  
  
  Future Improvements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database Integration&lt;/strong&gt;: I plan to use &lt;strong&gt;PostgreSQL(with Atlas)&lt;/strong&gt; to store historical rate data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Analysis&lt;/strong&gt;: I want to build a Python component to analyze the rate trends using Pandas and visualize the data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔗 Links
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Repository&lt;/strong&gt;: &lt;a href="https://github.com/kskiii/yenup-app" rel="noopener noreferrer"&gt;https://github.com/kskiii/yenup-app&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>gcp</category>
      <category>githubactions</category>
      <category>go</category>
      <category>cicd</category>
    </item>
  </channel>
</rss>
