<?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: Jerome Samuels</title>
    <description>The latest articles on DEV Community by Jerome Samuels (@jjsam).</description>
    <link>https://dev.to/jjsam</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%2F3335894%2Fcc2bf1ed-0b41-4983-8230-4f42db8da093.jpg</url>
      <title>DEV Community: Jerome Samuels</title>
      <link>https://dev.to/jjsam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jjsam"/>
    <language>en</language>
    <item>
      <title>When I Stopped Just Building Things</title>
      <dc:creator>Jerome Samuels</dc:creator>
      <pubDate>Wed, 21 Jan 2026 09:12:34 +0000</pubDate>
      <link>https://dev.to/jjsam/when-i-stopped-just-building-things-o2i</link>
      <guid>https://dev.to/jjsam/when-i-stopped-just-building-things-o2i</guid>
      <description>&lt;p&gt;At the start of my career, my role was simple; I built systems that solution architects had designed. I didn’t need to think too hard about the bigger picture as my job was to build my part well.&lt;/p&gt;

&lt;p&gt;As I’ve grown in my career however, that’s started to change.&lt;/p&gt;

&lt;p&gt;Now I’m much closer to the design side of things, and that’s forced a shift in how I think. I’m no longer asking myself “how do I build this?”, but “what should we actually build?”, “what does the whole system need to look like?” and “what does the client actually need?”. That’s been a bigger mindset change than I expected.&lt;/p&gt;

&lt;p&gt;These are some of the lessons I’ve learned as I’ve shifted into a more delivery-centred mindset.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Power of Asking Questions &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%2Fk6z7cgxkqnpyr7xiuus3.png" alt="multiple hands raised to ask a question" width="800" height="467"&gt;
&lt;/h2&gt;

&lt;p&gt;Earlier on, if an architectural design was put in front of me, I’d mostly just accept it and focus on implementing it as well as I could.&lt;/p&gt;

&lt;p&gt;As I moved closer to delivery and design, that approach stopped being sufficient.&lt;/p&gt;

&lt;p&gt;A big part of my mindset shift has been learning to ask better questions. That includes questions about the infrastructure itself and why certain architectural decisions were made, as well as questions that help uncover what a client actually needs.&lt;/p&gt;

&lt;p&gt;Questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What problem is this meant to solve?&lt;/li&gt;
&lt;li&gt;What constraints led us here?&lt;/li&gt;
&lt;li&gt;What assumptions are we making?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same applies when talking to clients. Sometimes what they ask for is a solution they have already decided on, rather than one that solves the problem they’re trying to fix. Asking clarifying questions helps surface that underlying need without making anyone feel challenged or talked down to. It also reduces the risk of delivering something that doesn’t truly solve the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Is Really Just a Trail of Decisions
&lt;/h2&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%2Fsizoevw5m8pheg70bwey.gif" 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%2Fsizoevw5m8pheg70bwey.gif" alt="Zoe Saldana making a decision" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used to think of architecture as a static thing, something that you draw up, agree on, and then implement. In reality, even if you start with a diagram or a high-level design, the real architecture is shaped over time by lots of smaller choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A service that seemed right at the start turns out not to quite fit&lt;/li&gt;
&lt;li&gt;A deadline forces a simpler approach than originally planned&lt;/li&gt;
&lt;li&gt;A “temporary” workaround sticks around longer than expected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these decisions moves the system slightly, so that by the end of the project, what’s running in production is the result of all those choices combined, not just the original design.&lt;/p&gt;

&lt;p&gt;That’s where my idea for an architectural diary came from.&lt;/p&gt;

&lt;p&gt;Instead of trying to perfectly document an architecture, I write down key decisions as they happen. What we decided, what other options we talked about, and why we landed where we did. This has changed how I think about solution architecture by helping me focus on making sensible calls with the information available at the time.&lt;/p&gt;

&lt;p&gt;The diary preserves context, which is usually the first thing to get lost once a project ends.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t Let Perfect Be The Enemy of Good
&lt;/h2&gt;

&lt;p&gt;As an engineer, my scope tended to be quite narrow as I’d only focus on the thing that was in front of me. How clean is the solution? Can it be more elegant or more scalable?&lt;/p&gt;

&lt;p&gt;With a delivery mindset, those questions haven’t disappeared, but now they sit alongside others.&lt;/p&gt;

&lt;p&gt;I now spend more time considering trade-offs. Is this good enough to get us live by the deadline? Is the extra complexity actually worth it? Does this decision help or slow down delivery? In many cases, the most technically impressive option is not the one that best serves the project.&lt;/p&gt;

&lt;p&gt;That took some adjustment. Letting go of perfect solutions in favour of pragmatic ones feels wrong when you’ve spent a long time being rewarded for how technically neat your solution is. But once I started focusing on outcomes rather than individual components, I realised that architecture often involves deciding which problems are worth solving now, and which ones can wait.&lt;/p&gt;

&lt;h2&gt;
  
  
  Take Initiative
&lt;/h2&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%2F0f6a0emtea3a42unhpfq.jpg" 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%2F0f6a0emtea3a42unhpfq.jpg" alt="cartoon figure stepping out of line" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the biggest mindset changes for me has been realising that delivery doesn’t reward waiting.&lt;/p&gt;

&lt;p&gt;As an engineer, it was easy to wait for clear requirements or explicit instructions. Working in delivery, that often means progress stalls.&lt;/p&gt;

&lt;p&gt;Taking initiative means proposing options and moving conversations forward even when things are unclear. It can be as simple as saying, “This is what I’m thinking, does that align with what you need?”&lt;br&gt;
This has pushed me outside my comfort zone, but it’s also where I’ve seen the most growth. Delivery and architecture both involve uncertainty, and initiative is what keeps progress moving.&lt;/p&gt;

&lt;p&gt;Shifting from an engineer mindset to a delivery mindset has been less about changing roles and more about changing how I think. Asking better questions, taking initiative, and capturing decisions as they happen has helped me learn from real projects, not just complete them. Over time, that has shaped how I approach solution architecture and delivery as a whole.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>productivity</category>
      <category>architecture</category>
      <category>career</category>
    </item>
    <item>
      <title>Enhancing S3 Security: My Journey from ClamAV to GuardDuty Malware Scanning</title>
      <dc:creator>Jerome Samuels</dc:creator>
      <pubDate>Tue, 08 Jul 2025 19:59:17 +0000</pubDate>
      <link>https://dev.to/jjsam/enhancing-s3-security-my-journey-from-clamav-to-guardduty-malware-scanning-135h</link>
      <guid>https://dev.to/jjsam/enhancing-s3-security-my-journey-from-clamav-to-guardduty-malware-scanning-135h</guid>
      <description>&lt;p&gt;With its ability to store virtually unlimited amounts of data, Amazon S3 is an extremely popular choice for customers looking to store data in the cloud. On a recent project, our client relied on S3 to store uploaded files. However, during the project, a key requirement emerged, ensuring that every uploaded file was free from malware before being processed. To address this, I initially implemented a serverless scanning solution using ClamAV, an open-source antivirus software, alongside AWS Lambda to scan files as they were uploaded to S3. While this setup worked as intended, it also introduced unexpected challenges, particularly during periods of high file upload activity. Shortly after completing the ClamAV solution, AWS introduced GuardDuty S3 Malware Protection, a managed service that simplifies malware scanning.  In this article, I’ll share my experiences with both solutions and explain why GuardDuty S3 Malware Protection ultimately proved to be the superior choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Scanning S3 File Uploads Is Crucial
&lt;/h2&gt;

&lt;p&gt;Hackers often exploit software vulnerabilities to upload files containing malware, or other malicious code, potentially wreaking havoc on systems and compromising sensitive data. A notable example of this is the 2017 Equifax hack, one of the most infamous data breaches in history.&lt;/p&gt;

&lt;p&gt;In this case, attackers exploited a vulnerability to infiltrate Equifax’s systems and used it to upload malicious files, allowing them to dig into Equifax’s systems and steal sensitive info from over 147 million people. All because a gap in security allowed attackers to upload the wrong kind of file.&lt;/p&gt;

&lt;p&gt;This underscores the importance of implementing proactive measures to detect and mitigate threats before they escalate. Whether an organisation is managing sensitive customer data or simply hosting files, failing to account for malicious uploads can have devastating and far-reaching implications.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Initial Approach: Lambda + ClamAV
&lt;/h2&gt;

&lt;p&gt;My initial approach to identify potentially malicious S3 uploads consisted of two lambda functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Scan-File Lambda:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An S3 event triggered this lambda whenever a file was uploaded
Each file would then be downloaded into the lambda’s /tmp directory.&lt;/li&gt;
&lt;li&gt;Scan the file using ClamAV (scan capability derived from a custom lambda layer, the details of which can be found &lt;a href="https://dev.to/sutt0n/scanning-files-on-lambda-with-a-clamav-lambda-layer-475c"&gt;here&lt;/a&gt;), and delete any files where malware is detected.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Update-Malware-Definitions Lambda:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Triggered by Eventbridge scheduler every 12 hours, this function downloaded the up to date malware definitions used by ClamAV and stored them in an S3 bucket.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Drawbacks: Bottlenecks During High Activity
&lt;/h2&gt;

&lt;p&gt;While the solution worked well under low to moderate traffic, it struggled when the upload rate spiked significantly. Each Lambda invocation spent around 30 seconds scanning a single file which led to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lambda Concurrency Issues:&lt;/strong&gt; Multiple files arriving simultaneously caused a surge in Lambda invocations, quickly hitting lambda concurrency limits.&lt;br&gt;
&lt;strong&gt;Delayed Processing:&lt;/strong&gt; The long execution time per file created bottlenecks, resulting in slower handling of uploads.&lt;/p&gt;

&lt;p&gt;These issues undermined the reliability and scalability of the solution, requiring me to pivot to something that could better handle large numbers of uploads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving to GuardDuty Malware Protection
&lt;/h2&gt;

&lt;p&gt;To address these challenges, I looked to a new managed service from AWS: &lt;a href="https://aws.amazon.com/blogs/aws/introducing-amazon-guardduty-malware-protection-for-amazon-s3/" rel="noopener noreferrer"&gt;GuardDuty Malware Protection.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GuardDuty continuously scans new files as they’re uploaded to select S3 buckets and removes the operational overhead traditionally associated with scanning for malware at scale. Once a file is scanned, it can be given a tag detailing the outcome of the scan, which can then be used for post-scan processing.&lt;/p&gt;

&lt;p&gt;With this knowledge, I knew that GuardDuty was the right service for the job. I repurposed the Scan file lambda, modifying the code to check the S3 file’s tag rather than perform a scan itself. If the tag suggested the presence of malware, the lambda moved the file into a separate S3 bucket designated as the quarantine bucket.&lt;/p&gt;

&lt;p&gt;This approach provided the following advantages:&lt;br&gt;
&lt;strong&gt;Seamless Integration:&lt;/strong&gt; GuardDuty integrates easily with S3 and eventbridge, allowing the malware scan to trigger downstream processing.&lt;br&gt;
&lt;strong&gt;Real-Time Insights:&lt;/strong&gt; The service provides clear visibility into the scan status of files.&lt;/p&gt;

&lt;p&gt;By switching to GuardDuty, I eliminated the performance bottlenecks and concurrency issues of the previous lambda based setup while also simplifying the upfront work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A diagram of my solution is below.&lt;/strong&gt;&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%2Fkcg8z9rk4v6b32ot3jcs.jpg" 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%2Fkcg8z9rk4v6b32ot3jcs.jpg" alt=" " width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;Reflecting on this journey, a few key insights stand out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand Workload Scalability:&lt;/strong&gt; While Lambda is a powerful tool, its scalability is hindered when high-latency operations, like ClamAV malware scanning, increase execution time; hitting lambda concurrency limits.&lt;br&gt;
&lt;strong&gt;Evaluate Managed Solutions:&lt;/strong&gt; AWS’s managed services, such as GuardDuty, often provide specialised solutions with better performance and reliability than custom architectures.&lt;br&gt;
&lt;strong&gt;Keep it Simple:&lt;/strong&gt; GuardDuty significantly reduced the complexity of my setup, allowing me to focus on other critical aspects of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Scanning files as they hit an S3 bucket remains a critical security practice. While my initial solution with ClamAV and Lambda demonstrated the feasibility of serverless malware scanning, it also highlighted the importance of accounting for spikes and maintaining operational simplicity.&lt;/p&gt;

&lt;p&gt;For anyone considering file scanning in the cloud, I highly recommend exploring GuardDuty Malware Protection for S3. It not only enhances security but also removes the burden of maintaining a custom solution. However, there are some considerations to keep in mind. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;GuardDuty doesn’t scan files immediately upon upload, so if you have an event-driven architecture that requires the files to be already scanned, you’ll need to implement a decoupling mechanism to ensure those scans have taken place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Like other AWS services, GuardDuty has &lt;a href="https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection-s3-quotas-guardduty.html" rel="noopener noreferrer"&gt;quotas&lt;/a&gt;, like maximum file size, which may require workarounds.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Thanks
&lt;/h2&gt;

&lt;p&gt;Thanks for reading. If you have any questions, feel free to ask in the comments! I'd also love to hear from anyone who's experimented with similar setups. 🙂&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>cloudsecurity</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
