<?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: CODELEVEL - Jacob Binczyk</title>
    <description>The latest articles on DEV Community by CODELEVEL - Jacob Binczyk (@codelevel).</description>
    <link>https://dev.to/codelevel</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4170771%2F1105efdb-926b-41af-a82a-9f0e6c9e4c52.png</url>
      <title>DEV Community: CODELEVEL - Jacob Binczyk</title>
      <link>https://dev.to/codelevel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codelevel"/>
    <language>en</language>
    <item>
      <title>How to check your server has the php2shell patch</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Mon, 26 Oct 2026 16:11:25 +0000</pubDate>
      <link>https://dev.to/codelevel/how-to-check-your-server-has-the-php2shell-patch-2agh</link>
      <guid>https://dev.to/codelevel/how-to-check-your-server-has-the-php2shell-patch-2agh</guid>
      <description>&lt;p&gt;On 21 October the PHP team &lt;a href="https://discourse.thephp.foundation/t/announce-php-8-2-35-released/6282" rel="noopener noreferrer"&gt;released&lt;/a&gt; 8.2.35, 8.3.36, 8.4.27 and 8.5.12, the php2shell patch for &lt;a href="https://blog.qualys.com/vulnerabilities-threat-research/2026/10/20/php-announces-critical-security-release-for-two-vulnerabilities" rel="noopener noreferrer"&gt;CVE-2026-109618 and CVE-2026-109619&lt;/a&gt;. Both flaws let an attacker run code on the server without logging in, and both are now being exploited. If your site or online shop runs on PHP, check this week that the process actually serving it has the fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The flaws are being exploited, so patch now rather than at the next maintenance window.&lt;/li&gt;
&lt;li&gt;After updating, restart PHP-FPM or Apache, and rebuild your container images.&lt;/li&gt;
&lt;li&gt;The PHP team ships fixes for PHP 8.2 only until 31 December 2026.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The flaws are already being exploited
&lt;/h2&gt;

&lt;p&gt;News of the flaws and the release date leaked the day before the planned release. According to &lt;a href="https://thehackernews.com/2026/10/php-issues-emergency-patches-for-two.html" rel="noopener noreferrer"&gt;The Hacker News&lt;/a&gt;, watchTowr reported active attack attempts just 19&amp;nbsp;minutes after the patches went out, and by early on 22 October Cloudflare had &lt;a href="https://thehackernews.com/2026/10/php2shell-exploit-attempts-hit-millions.html" rel="noopener noreferrer"&gt;counted millions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On 26 October &lt;a href="https://www.bleepingcomputer.com/news/security/php2shell-security-flaws-now-sucessfully-exploited-in-the-wild/" rel="noopener noreferrer"&gt;BleepingComputer reported&lt;/a&gt; a confirmed successful takeover. It happened on a honeypot running Apache with mod_php and PHP 8.4.26, and the researcher Marcus Hutchins confirmed the finding independently. A day earlier Aviatrix &lt;a href="https://aviatrix.ai/threat-research-center/php2shell-exploitation-government-cve-2026-109618-lazarus-ai-assisted-hacking/" rel="noopener noreferrer"&gt;described a breach&lt;/a&gt; at an unnamed European government body, where the attackers left a web shell on an unpatched server to keep their access.&lt;/p&gt;

&lt;p&gt;Servers running mod_php in Apache are the most exposed, but PHP-FPM, php-cgi, FrankenPHP and LiteSpeed are affected too. With millions of attempts, any unpatched PHP server can expect this traffic, small ones included.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to check this week
&lt;/h2&gt;

&lt;p&gt;An installed package is not enough on its own. Go through these in order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The package version, not the output of &lt;code&gt;php -v&lt;/code&gt;. Ubuntu 24.04 backported the fix into its own PHP 8.3.6, so &lt;code&gt;php -v&lt;/code&gt; still says 8.3.6. The fix is in package &lt;a href="https://ubuntu.com/security/CVE-2026-109618" rel="noopener noreferrer"&gt;8.3.6-0ubuntu0.24.04.13&lt;/a&gt; or newer. Debian 12 has &lt;a href="https://security-tracker.debian.org/tracker/CVE-2026-109618" rel="noopener noreferrer"&gt;8.2.35&lt;/a&gt;, and RHEL 9 got the same version in &lt;a href="https://access.redhat.com/errata/RHSA-2026:87072" rel="noopener noreferrer"&gt;RHSA-2026:87072&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A restart. PHP-FPM workers and Apache with mod_php keep the old code in memory until you restart them.&lt;/li&gt;
&lt;li&gt;Containers. Updating the host does not change the PHP inside your image, so rebuild it with &lt;code&gt;docker build --pull&lt;/code&gt; and deploy it. If your Dockerfile pins a version such as &lt;code&gt;php:8.2.34-fpm&lt;/code&gt;, bump that first.&lt;/li&gt;
&lt;li&gt;Hosting. On shared hosting the provider patches PHP, so ask them whether the fix is in. As &lt;a href="https://www.malwarebytes.com/blog/bugs/2026/10/php2shell-why-websites-are-going-offline-for-emergency-security-updates" rel="noopener noreferrer"&gt;Malwarebytes&lt;/a&gt; points out, updating WordPress does not update PHP, which is a separate engine the site runs on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The commands for PHP from Ubuntu 24.04 and RHEL 9 packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ubuntu 24.04 (Debian 12: replace 8.3 with 8.2, package 8.2.35-1~deb12u1 or newer)&lt;/span&gt;
dpkg-query &lt;span class="nt"&gt;-W&lt;/span&gt; php8.3-fpm   &lt;span class="c"&gt;# 8.3.6-0ubuntu0.24.04.13 or newer&lt;/span&gt;
&lt;span class="nb"&gt;sudo ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /proc/&lt;span class="si"&gt;$(&lt;/span&gt;pgrep &lt;span class="nt"&gt;-o&lt;/span&gt; php-fpm8.3&lt;span class="si"&gt;)&lt;/span&gt;/exe
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart php8.3-fpm

&lt;span class="c"&gt;# RHEL 9, php:8.2 module&lt;/span&gt;
rpm &lt;span class="nt"&gt;-q&lt;/span&gt; php-fpm   &lt;span class="c"&gt;# 8.2.35 or newer&lt;/span&gt;
&lt;span class="nb"&gt;sudo ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /proc/&lt;span class="si"&gt;$(&lt;/span&gt;pgrep &lt;span class="nt"&gt;-o&lt;/span&gt; php-fpm&lt;span class="si"&gt;)&lt;/span&gt;/exe
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart php-fpm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the path ends in &lt;code&gt;(deleted)&lt;/code&gt;, the process is still running the version from before the update and needs a restart. With mod_php you restart Apache itself: &lt;code&gt;systemctl restart apache2&lt;/code&gt; on Debian and Ubuntu, &lt;code&gt;systemctl restart httpd&lt;/code&gt; on RHEL.&lt;/p&gt;

&lt;h2&gt;
  
  
  PHP 8.2 gets fixes until 31 December
&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="https://www.php.net/supported-versions.php" rel="noopener noreferrer"&gt;PHP support schedule&lt;/a&gt;, security fixes for PHP 8.2 end on 31 December 2026. If a similar flaw turns up in January, the PHP team will not release a fixed 8.2, so the official Docker images will not get one either. That is what happened this week to PHP 8.1 and older, which got only source patches.&lt;/p&gt;

&lt;p&gt;Debian, Red Hat and some hosts backport fixes to older versions, but on their own schedules. If your 8.2 comes from their packages, ask how long they will keep shipping fixes. If it comes from php.net or the official Docker image, plan the move before the end of the year. I would go straight to 8.4, which gets fixes until the end of 2028, a year longer than 8.3. Staging first, then production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who decides when you cannot patch straight away
&lt;/h2&gt;

&lt;p&gt;Sometimes the update has to wait. Then someone has to choose between a &lt;a href="https://bleepingcomputer.com/news/security/php-ships-emergency-patches-for-critical-php2shell-flaws" rel="noopener noreferrer"&gt;workaround&lt;/a&gt; and taking the service offline. A workaround means, for example, turning off &lt;code&gt;session.upload_progress.enabled&lt;/code&gt;, lowering the request size limit or adding a WAF rule. It does not replace the patch, but it shortens the time the server is an easy target. Some companies took their sites offline for a few hours, and that was a sensible call.&lt;/p&gt;

&lt;p&gt;Write down on a single page who makes that decision in your company, how to reach them quickly, which services can go offline without much harm and who does the update itself. My &lt;a href="https://codelevel.pl/en/services/maintenance/" rel="noopener noreferrer"&gt;maintenance service&lt;/a&gt; includes alerts and a response in business hours, and I handle critical incidents in the evening too.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/php2shell-patch-check-server/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>SSL certificate validity drops to 100 days in March 2027</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Mon, 26 Oct 2026 12:20:11 +0000</pubDate>
      <link>https://dev.to/codelevel/ssl-certificate-validity-drops-to-100-days-in-march-2027-30dk</link>
      <guid>https://dev.to/codelevel/ssl-certificate-validity-drops-to-100-days-in-march-2027-30dk</guid>
      <description>&lt;p&gt;From 15&amp;nbsp;March 2027 no newly issued public TLS certificate, still usually called an SSL certificate, may be valid for more than 100&amp;nbsp;days. The limit is set by the &lt;a href="https://github.com/cabforum/servercert/blob/main/docs/BR.md" rel="noopener noreferrer"&gt;CA/B Forum Baseline Requirements&lt;/a&gt;, the rules every certificate authority has to follow. Let's Encrypt moves first: &lt;a href="https://letsencrypt.org/2026/10/07/64-day-certs.html" rel="noopener noreferrer"&gt;from 10&amp;nbsp;February 2027&lt;/a&gt; its certificates will last 64&amp;nbsp;days by default.&lt;/p&gt;

&lt;p&gt;If your certificate renews itself, all you need to check is that someone hears when a renewal fails. A certificate installed by hand will have to be replaced at least three times a year from March, and in practice four.&lt;/p&gt;

&lt;h2&gt;
  
  
  The limit falls from 200 to 100&amp;nbsp;days
&lt;/h2&gt;

&lt;p&gt;A certificate issued before 15&amp;nbsp;March 2026 could be valid for 398&amp;nbsp;days, just over a year, which is where the habit of a yearly swap comes from. The limit has been 200&amp;nbsp;days since 15&amp;nbsp;March 2026, so a certificate issued today won't last even seven months. From 15&amp;nbsp;March 2027 it falls to 100&amp;nbsp;days, and from 15&amp;nbsp;March 2029 to 47.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The chart for this part is in the &lt;a href="https://codelevel.pl/en/insights/ssl-certificate-validity-2027/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the issuer and the expiry date
&lt;/h2&gt;

&lt;p&gt;Your browser shows the issuer and the expiry date in the certificate details when you click the icon next to the address. For several hostnames this command is quicker; it runs on Linux with OpenSSL 1.1.1 or 3.x, with your own hostname in both places:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; | openssl s_client &lt;span class="nt"&gt;-connect&lt;/span&gt; shop.example.com:443 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-servername&lt;/span&gt; shop.example.com 2&amp;gt;/dev/null &lt;span class="se"&gt;\&lt;/span&gt;
  | openssl x509 &lt;span class="nt"&gt;-noout&lt;/span&gt; &lt;span class="nt"&gt;-issuer&lt;/span&gt; &lt;span class="nt"&gt;-enddate&lt;/span&gt; &lt;span class="nt"&gt;-checkend&lt;/span&gt; 1209600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first line of output is the issuer and the second is &lt;code&gt;notAfter&lt;/code&gt;, the expiry date. The number &lt;code&gt;1209600&lt;/code&gt; is 14&amp;nbsp;days in seconds. With less time left, OpenSSL &lt;a href="https://github.com/openssl/openssl/blob/master/doc/man1/openssl-x509.pod.in" rel="noopener noreferrer"&gt;adds "Certificate will expire" and exits with an error&lt;/a&gt;, so the same command can go into a script that raises an alert.&lt;/p&gt;

&lt;p&gt;The issuer is a good clue to who renews the certificate: Let's Encrypt and Amazon usually mean automation, while with Sectigo or DigiCert someone most often bought a file and installed it by hand. Check every hostname separately, because a customer portal or a VPN gateway often has a different certificate from the website. Behind a proxied Cloudflare record or CloudFront the command shows the CDN's certificate, so run it once more on the server itself, with &lt;code&gt;127.0.0.1:443&lt;/code&gt; after &lt;code&gt;-connect&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Let's Encrypt renewal breaks
&lt;/h2&gt;

&lt;p&gt;Let's Encrypt &lt;a href="https://letsencrypt.org/2025/06/26/expiration-notification-service-has-ended.html" rel="noopener noreferrer"&gt;stopped sending expiry reminder emails&lt;/a&gt; on 4&amp;nbsp;June 2025. According to the &lt;a href="https://github.com/certbot/certbot/blob/main/certbot/docs/using.rst" rel="noopener noreferrer"&gt;certbot documentation&lt;/a&gt;, versions before 4.0 renew a certificate 30&amp;nbsp;days before expiry and 4.0 onwards once less than a third of its lifetime remains, so &lt;code&gt;certbot renew&lt;/code&gt; run from a timer or cron is in time either way.&lt;/p&gt;

&lt;p&gt;A certificate issued with &lt;code&gt;--manual&lt;/code&gt;, often a wildcard with a DNS record added by hand, won't renew on its own unless certbot gets a script that adds the record. Let's Encrypt &lt;a href="https://letsencrypt.org/2026/10/07/64-day-certs.html" rel="noopener noreferrer"&gt;suggests checking&lt;/a&gt; home-made scripts and cron jobs with a fixed interval, because they may now run too late. A web server that is never reloaded keeps serving the old certificate, so pass the reload command to certbot's &lt;code&gt;--deploy-hook&lt;/code&gt; and certbot will run it after every successful renewal.&lt;/p&gt;

&lt;h2&gt;
  
  
  ACM with email validation waits for a click
&lt;/h2&gt;

&lt;p&gt;Since 18&amp;nbsp;February 2026 AWS Certificate Manager &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/02/aws-certificate-manager-updates-default/" rel="noopener noreferrer"&gt;has issued public certificates valid for at most 198&amp;nbsp;days&lt;/a&gt;, and AWS says customers need to do nothing. With DNS validation, ACM &lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/dns-renewal-validation.html" rel="noopener noreferrer"&gt;renews the certificate on its own&lt;/a&gt; as long as it is in use by an AWS service, a load balancer for example, and ACM's CNAME records are still in DNS.&lt;/p&gt;

&lt;p&gt;With email validation, ACM &lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/email-renewal-validation.html" rel="noopener noreferrer"&gt;sends an email 45&amp;nbsp;days before expiry&lt;/a&gt; to addresses such as admin@ and webmaster@ at your domain. The certificate renews only after someone clicks the link in it, so with 198-day certificates someone has to click roughly every five months. You can't switch the validation method to DNS, so you have to &lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/email-validation.html" rel="noopener noreferrer"&gt;request a new certificate&lt;/a&gt; with DNS validation and swap it in on your services. It is worth doing now, because from 15&amp;nbsp;March 2028 the &lt;a href="https://github.com/cabforum/servercert/blob/main/docs/BR.md#122-relevant-dates" rel="noopener noreferrer"&gt;CA/B Forum rules&lt;/a&gt; forbid certificate authorities from validating by email to those addresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hand-installed certificates are slow to replace
&lt;/h2&gt;

&lt;p&gt;In October 2026 the main browsers &lt;a href="https://groups.google.com/a/mozilla.org/g/dev-security-policy/c/0R3XLJL6FuE/m/0XofdebrAAAJ" rel="noopener noreferrer"&gt;stopped trusting eight intermediate certificates&lt;/a&gt; of the certificate authority eMudhra, all within three days. Where certificates are installed by hand, the site then has to wait for a new certificate and for someone to install it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for a small team
&lt;/h2&gt;

&lt;p&gt;This week, check every hostname you use, in the browser or with the command, and note who issued each certificate.&lt;/p&gt;

&lt;p&gt;With Let's Encrypt there is nothing to replace, but nobody will warn you when renewal breaks. Add &lt;a href="https://letsencrypt.org/docs/monitoring-options/" rel="noopener noreferrer"&gt;monitoring&lt;/a&gt; that alerts you 14&amp;nbsp;days before expiry. I can also run it alongside uptime and disk alerts as part of &lt;a href="https://codelevel.pl/en/services/maintenance/" rel="noopener noreferrer"&gt;server maintenance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In ACM, only the certificates with email validation need replacing: the ones someone approved by clicking a link in an email from Amazon. Request new ones with DNS validation before the next email arrives.&lt;/p&gt;

&lt;p&gt;Replace a commercial certificate you install by hand wherever you can: on an ordinary server with one from Let's Encrypt, and on a load balancer or CloudFront with &lt;a href="https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html" rel="noopener noreferrer"&gt;one from ACM&lt;/a&gt;. Where you can't, put the expiry dates in a calendar and in your monitoring. Do it before 15&amp;nbsp;March 2027 or, failing that, get your next commercial certificate issued before that day, because it can still be valid for up to 200&amp;nbsp;days instead of 100.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/ssl-certificate-validity-2027/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>What Magento hosting on AWS costs a month</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Wed, 21 Oct 2026 15:53:02 +0000</pubDate>
      <link>https://dev.to/codelevel/what-magento-hosting-on-aws-costs-a-month-3off</link>
      <guid>https://dev.to/codelevel/what-magento-hosting-on-aws-costs-a-month-3off</guid>
      <description>&lt;p&gt;Running a small Magento shop on AWS in Frankfurt costs from about USD&amp;nbsp;204 to about USD&amp;nbsp;804 a month, according to &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;AWS price lists as of 12&amp;nbsp;October 2026&lt;/a&gt;. Where you land depends on how many services you hand to AWS and whether you pay for a standby in a second zone. On shared hosting, Magento 2.4 usually won't even install, because it needs a search engine that cheap plans don't include.&lt;/p&gt;

&lt;p&gt;I assumed a shop with up to about 10,000 products and about 30 people browsing at once, with most pages served from the Varnish cache, so 4&amp;nbsp;vCPU and 16&amp;nbsp;GB of RAM in total are enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Magento 2.4 needs a separate search engine
&lt;/h2&gt;

&lt;p&gt;Since Magento 2.4, Adobe &lt;a href="https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/prerequisites/search-engine/overview" rel="noopener noreferrer"&gt;requires&lt;/a&gt; Elasticsearch or OpenSearch in every installation. For the latest release, 2.4.9, the &lt;a href="https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/system-requirements" rel="noopener noreferrer"&gt;system requirements table&lt;/a&gt; lists only OpenSearch 3.&lt;/p&gt;

&lt;p&gt;Hostinger's &lt;a href="https://www.hostinger.com/support/which-programming-languages-and-frameworks-are-supported-at-hostinger/" rel="noopener noreferrer"&gt;help centre&lt;/a&gt; says Elasticsearch isn't available on its web and cloud plans, so Magento 2 needs a VPS. A &lt;a href="https://www.hostinger.com/vps/magento-hosting" rel="noopener noreferrer"&gt;Hostinger VPS for Magento&lt;/a&gt; with 4&amp;nbsp;vCPU and 16&amp;nbsp;GB of RAM costs about USD&amp;nbsp;29 a month after the promotional period, according to its price list on 14&amp;nbsp;October 2026.&lt;/p&gt;

&lt;p&gt;On a VPS you administer the system, the database and OpenSearch yourself, and keep a backup off the server. My post on &lt;a href="https://codelevel.pl/en/insights/hetzner-or-aws-small-company/" rel="noopener noreferrer"&gt;Hetzner or AWS for a small company&lt;/a&gt; covers how much work that is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three versions of the same shop on AWS
&lt;/h2&gt;

&lt;p&gt;I priced all three at on-demand rates before VAT, in Frankfurt, with 200&amp;nbsp;GB of data transfer out to the internet a month.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A single EC2 server with 4&amp;nbsp;vCPU and 16&amp;nbsp;GB of RAM runs the whole shop, database and search engine included, for about USD&amp;nbsp;204. In practice it is a VPS inside AWS, so when that machine goes down, the shop stops.&lt;/li&gt;
&lt;li&gt;For about USD&amp;nbsp;428, the application gets a smaller server, and the database, cache and search engine move to managed AWS services. All of it runs in one Availability Zone, one of three separate groups of data centres in the Frankfurt region, so there is still nothing to fail over to.&lt;/li&gt;
&lt;li&gt;The version with standby has two application servers behind a load balancer, a database with a standby copy in a second zone, two cache nodes, and images in S3 served through a CDN. It costs about USD&amp;nbsp;804. Only search stays on one node in one zone, so if it fails, category pages and search stop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;The chart for this part is in the &lt;a href="https://codelevel.pl/en/insights/magento-hosting-on-aws-cost/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
The &lt;a href="https://codelevel.pl/en/calculator/#type=web&amp;amp;amount=804&amp;amp;currency=usd&amp;amp;ri=0&amp;amp;region=eu-central-1" rel="noopener noreferrer"&gt;calculator&lt;/a&gt; shows a similar setup under the “Web application, shop or CMS” profile, next to Hetzner and OVH prices.&lt;/p&gt;

&lt;h2&gt;
  
  
  A second zone nearly doubles the bill
&lt;/h2&gt;

&lt;p&gt;The database adds the most. RDS Multi-AZ &lt;a href="https://aws.amazon.com/rds/mysql/pricing/" rel="noopener noreferrer"&gt;keeps a standby instance in another zone&lt;/a&gt; and &lt;a href="https://aws.amazon.com/rds/features/multi-az/" rel="noopener noreferrer"&gt;fails the database over to it&lt;/a&gt; when the primary stops working. AWS charges twice the single-zone rate for both the instance and its storage.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://codelevel.pl/en/case-studies/magento-shop-migration-to-aws/" rel="noopener noreferrer"&gt;Magento shop I moved to AWS&lt;/a&gt; runs on similar services: RDS MySQL, OpenSearch, Redis, Varnish and a CDN. Its hosting bill is higher than before the move, because the shop had to hold up through campaign traffic peaks and recover quickly from a failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for a small shop
&lt;/h2&gt;

&lt;p&gt;If the shop sells evenly all year and can live with a few hours of downtime after a server failure, a VPS or a Magento hosting plan with OpenSearch is enough.&lt;/p&gt;

&lt;p&gt;For a shop that makes its money in campaigns and can't go down while they run, I recommend the third version. In the second version you pay for managed services, yet when its only application server or database fails, the shop goes offline.&lt;/p&gt;

&lt;p&gt;Before you choose the third version, open the sales report in the Magento admin and work out the revenue per hour on the best day of your last campaign. Multiply it by the hours a server failure would keep the shop down. Compare that with what the third version would cost you extra over a year: the gap between about USD&amp;nbsp;804 and your current monthly hosting bill, times twelve. If one outage costs you more, the standby pays for itself even with one failure a year.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/magento-hosting-on-aws-cost/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>devops</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Hetzner or AWS for a small company</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Tue, 20 Oct 2026 21:01:06 +0000</pubDate>
      <link>https://dev.to/codelevel/hetzner-or-aws-for-a-small-company-jfc</link>
      <guid>https://dev.to/codelevel/hetzner-or-aws-for-a-small-company-jfc</guid>
      <description>&lt;p&gt;In the example below, Hetzner costs 29–36% of the AWS on-demand bill for a steady workload. You pay the difference back in work, because Hetzner has no managed database, and someone has to own the backups, failover, patching and alerts. On an AWS bill of about USD&amp;nbsp;750 a month the saving on Hetzner does not cover maintenance, so the move does not pay back. In the example with a bill of about USD&amp;nbsp;2,700, you keep about a third.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small SaaS on AWS and on Hetzner
&lt;/h2&gt;

&lt;p&gt;For the &lt;a href="https://codelevel.pl/en/calculator/" rel="noopener noreferrer"&gt;calculator&lt;/a&gt; I costed a handful of typical architectures using prices from 23 September 2026. One is a small SaaS in Frankfurt: an application in containers, a PostgreSQL database with a standby in a second zone, a cache, file storage and a CDN. On Hetzner the same thing runs on five cloud servers, or on two dedicated servers plus one small cloud server. Add a load balancer, Object Storage in place of S3, an outside CDN, and backups at Hetzner and outside it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setup&lt;/th&gt;
&lt;th&gt;Per month, net, USD&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS on-demand&lt;/td&gt;
&lt;td&gt;746&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS with one-year reservations&lt;/td&gt;
&lt;td&gt;597&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner Cloud&lt;/td&gt;
&lt;td&gt;215&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hetzner dedicated servers&lt;/td&gt;
&lt;td&gt;271&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What you take on when you leave AWS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.hetzner.com/cloud" rel="noopener noreferrer"&gt;Hetzner Cloud&lt;/a&gt; gives you servers, private networks, firewalls and load balancers, but no managed database and no managed Kubernetes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You run the database, its replica and failover yourself, for example PostgreSQL with Patroni and etcd on three servers. With RDS Multi-AZ, AWS &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.MultiAZSingleStandby.html" rel="noopener noreferrer"&gt;keeps a standby in another zone&lt;/a&gt; and fails over to it.&lt;/li&gt;
&lt;li&gt;Hetzner Cloud &lt;a href="https://docs.hetzner.com/cloud/servers/backups-snapshots/overview/" rel="noopener noreferrer"&gt;copies the server's disk once a day&lt;/a&gt;, while RDS &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PIT.html" rel="noopener noreferrer"&gt;restores the database to a point in time you pick&lt;/a&gt;. To get the same, you archive the WAL, for example with pgBackRest, to storage outside Hetzner, and test the restore regularly.&lt;/li&gt;
&lt;li&gt;You install OS and PostgreSQL patches yourself, where on Fargate and RDS AWS does it. The alert about a failed database comes to you, evenings included.&lt;/li&gt;
&lt;li&gt;Spare capacity has to be planned ahead. Since 26 June Hetzner has been &lt;a href="https://status.hetzner.com/incident/0a75c7ae-3377-41dc-aabe-601063724d24" rel="noopener noreferrer"&gt;stopping some customers from creating new cloud servers&lt;/a&gt;, and the restriction was still in place on 8 October. I covered what that means, along with the June price rises, in the &lt;a href="https://codelevel.pl/en/insights/ovh-hetzner-price-rises-october-2026/" rel="noopener noreferrer"&gt;post on OVH and Hetzner prices&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hetzner takes cloud tickets at any hour, but general enquiries are handled &lt;a href="https://docs.hetzner.com/general/infrastructure-and-availability/support-team-opening-hours/" rel="noopener noreferrer"&gt;on weekdays from 8 a.m. to 6 p.m. CET&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much work that is
&lt;/h2&gt;

&lt;p&gt;The calculator adds maintenance to the Hetzner side, because server prices alone can't be compared fairly with managed services. The dedicated setup is three machines, so my Business plan at EUR&amp;nbsp;470 net a month, about USD&amp;nbsp;540, covers it. That includes 4 hours of work, patching and a monthly restore test, but restoring the database to a point in time comes only with the Growth plan. If someone on your team does it instead, price their hours at their rate.&lt;/p&gt;

&lt;p&gt;After maintenance the difference is gone: Hetzner with the Business plan costs about USD&amp;nbsp;810 a month, more than AWS. Five cloud servers need the Growth plan at EUR&amp;nbsp;1,170, so nothing is left there either, and the same goes for one-year reservations on AWS. The migration costs from EUR&amp;nbsp;2,300 net, and I deduct the exit plan's price from it if you order the migration within 90 days of the plan, so at this bill there is nothing to pay it back from.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to stay on AWS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Your traffic spikes, say in peak season or after a campaign. On AWS, Fargate adds tasks for the peak if you set up autoscaling. Hetzner Cloud also &lt;a href="https://docs.hetzner.com/cloud/billing/faq/" rel="noopener noreferrer"&gt;bills by the hour&lt;/a&gt;, but you have to script the scaling yourself, and a dedicated server is paid for the whole month.&lt;/li&gt;
&lt;li&gt;Your application uses Lambda, SQS or DynamoDB. Each one has to be replaced with something you run yourself, which usually means code changes.&lt;/li&gt;
&lt;li&gt;Your customers ask for specific certifications. AWS has SOC and PCI DSS among the programmes on its &lt;a href="https://aws.amazon.com/compliance/services-in-scope/" rel="noopener noreferrer"&gt;compliance list&lt;/a&gt;. Hetzner holds &lt;a href="https://docs.hetzner.com/general/company-and-policy/information-security-at-hetzner/" rel="noopener noreferrer"&gt;ISO/IEC 27001, and BSI C5 Type 2 for its cloud&lt;/a&gt;. If a customer contract requires a SOC 2 report, check this before you decide.&lt;/li&gt;
&lt;li&gt;Nobody in the company looks after servers, and you don't want to pay someone outside to do it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it means for a small team
&lt;/h2&gt;

&lt;p&gt;In the example above, the difference in the bill does not cover maintenance. For the larger application in the &lt;a href="https://codelevel.pl/en/services/cloud-exit/" rel="noopener noreferrer"&gt;cloud exit example&lt;/a&gt;, AWS costs about USD&amp;nbsp;2,700 a month, and after Hetzner dedicated servers and maintenance you keep about a third of that.&lt;/p&gt;

&lt;p&gt;Enter your bill in the &lt;a href="https://codelevel.pl/en/calculator/" rel="noopener noreferrer"&gt;calculator&lt;/a&gt; and look at the “You keep each month” line. The calculator also prices OVH dedicated servers, which come out cheaper than Hetzner's in this example: at USD&amp;nbsp;746 it shows up to USD&amp;nbsp;170 a month and a payback of 14&amp;nbsp;months. If the move doesn't pay back within two years, start by cutting the AWS bill.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/hetzner-or-aws-small-company/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>hetzner</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to set up AWS budget alerts</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Tue, 20 Oct 2026 21:00:25 +0000</pubDate>
      <link>https://dev.to/codelevel/how-to-set-up-aws-budget-alerts-39al</link>
      <guid>https://dev.to/codelevel/how-to-set-up-aws-budget-alerts-39al</guid>
      <description>&lt;p&gt;Set up one monthly budget in AWS Budgets with two alerts: one when actual spend reaches 80% of the amount, and one when the forecast for the end of the month goes over 100%. Budgets and their e-mail alerts are &lt;a href="https://aws.amazon.com/aws-cost-management/aws-budgets/pricing/" rel="noopener noreferrer"&gt;free&lt;/a&gt;, and the whole thing takes about fifteen minutes.&lt;/p&gt;

&lt;p&gt;The second safety net, Cost Anomaly Detection, is already running on many accounts. When it finds an anomaly, it sends a daily summary to the address the AWS account was opened with. Both can be up to a day late, and an e-mail on its own switches nothing off.&lt;/p&gt;

&lt;h2&gt;
  
  
  A monthly budget, step by step
&lt;/h2&gt;

&lt;p&gt;In the console, open Billing and Cost Management, then Budgets, then Create budget. Choose Customize (advanced) so you can &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/create-cost-budget.html" rel="noopener noreferrer"&gt;set the thresholds yourself&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Type Cost budget, period Monthly, Recurring budget, method Fixed. If AWS credits pay your bill, turn off credits in the budget options, because they are &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/budgets_budget" rel="noopener noreferrer"&gt;included by default&lt;/a&gt; and the budget then sees spend near zero.&lt;/li&gt;
&lt;li&gt;Amount: the average of your last three invoices plus 20%.&lt;/li&gt;
&lt;li&gt;First threshold (Add an alert threshold): 80, % of budgeted amount, Actual.&lt;/li&gt;
&lt;li&gt;Second threshold: 100, % of budgeted amount, Forecasted.&lt;/li&gt;
&lt;li&gt;Under Email recipients, enter the address the alerts should go to.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When spend speeds up mid-month, the forecast alert arrives long before the 80% one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The chart for this part is in the &lt;a href="https://codelevel.pl/en/insights/aws-budget-alerts-setup/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
The forecast needs &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-best-practices.html" rel="noopener noreferrer"&gt;about five weeks of data&lt;/a&gt;. On a new account the forecast alert stays silent until then, so add a third threshold at 100% of actual spend.&lt;/p&gt;

&lt;p&gt;For a test account that should stay within the Free Tier, use the &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budget-templates.html" rel="noopener noreferrer"&gt;Zero spend budget&lt;/a&gt; template instead. It e-mails you as soon as you spend anything beyond the free limits.&lt;/p&gt;
&lt;h2&gt;
  
  
  Who should get the e-mail
&lt;/h2&gt;

&lt;p&gt;AWS Budgets now sends a &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-email-recipients.html" rel="noopener noreferrer"&gt;verification e-mail&lt;/a&gt; to every new address. The link is valid for 12&amp;nbsp;hours, and to confirm the address you have to be signed in to the AWS account that added it. An unconfirmed address gets no alerts.&lt;/p&gt;

&lt;p&gt;That means a business owner who doesn't sign in to the console can't confirm their own address. For this case AWS suggests a distribution list whose membership you manage outside AWS. Create an address such as &lt;code&gt;billing-alerts@yourcompany.com&lt;/code&gt;, put yourself and your developer on it, and have the developer confirm it once in the console.&lt;/p&gt;

&lt;p&gt;Addresses added before verification was introduced show the status Expiring in the recipient list and keep working for a grace period. The documentation doesn't say how long that lasts, so choose Send Notification for each of them and confirm them now.&lt;/p&gt;
&lt;h2&gt;
  
  
  Cost Anomaly Detection
&lt;/h2&gt;

&lt;p&gt;A budget looks at the month's total. Cost Anomaly Detection looks for unusual jumps in individual services. On many accounts AWS &lt;a href="https://aws.amazon.com/blogs/aws-cloud-financial-management/new-aws-cost-explorer-users-can-now-automatically-detect-cost-anomalies-2/" rel="noopener noreferrer"&gt;set it up automatically at no cost&lt;/a&gt;: a monitor for AWS services and a daily e-mail summary. AWS then &lt;a href="https://aws.amazon.com/aws-cost-management/aws-cost-anomaly-detection/faqs/" rel="noopener noreferrer"&gt;only reports&lt;/a&gt; anomalies above $100 that are also more than 40% above expected spend.&lt;/p&gt;

&lt;p&gt;If your bill is a few hundred dollars a month, $100 is a high bar. In Billing and Cost Management, open Cost Anomaly Detection, then the Alert subscriptions tab, lower the amount in the &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/getting-started-ad.html" rel="noopener noreferrer"&gt;Threshold&lt;/a&gt; field to a level that would hurt, and add the same group address. If the Cost monitors tab is empty, create a monitor of the AWS services type.&lt;/p&gt;

&lt;p&gt;Cost Anomaly Detection &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/manage-ad.html" rel="noopener noreferrer"&gt;can take up to 24&amp;nbsp;hours to spot an anomaly&lt;/a&gt;, and it ignores an AWS service you've just started using for its first 10&amp;nbsp;days.&lt;/p&gt;
&lt;h2&gt;
  
  
  The same budget in Terraform
&lt;/h2&gt;

&lt;p&gt;If you keep your infrastructure in Terraform, put the budget in code. An example for the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/budgets_budget" rel="noopener noreferrer"&gt;aws_budgets_budget&lt;/a&gt; resource in AWS provider 6.x:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_budgets_budget"&lt;/span&gt; &lt;span class="s2"&gt;"monthly"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"monthly"&lt;/span&gt;
  &lt;span class="nx"&gt;budget_type&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"COST"&lt;/span&gt;
  &lt;span class="nx"&gt;time_unit&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MONTHLY"&lt;/span&gt;
  &lt;span class="nx"&gt;limit_amount&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"500"&lt;/span&gt;
  &lt;span class="nx"&gt;limit_unit&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"USD"&lt;/span&gt;

  &lt;span class="nx"&gt;notification&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;notification_type&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"FORECASTED"&lt;/span&gt;
    &lt;span class="nx"&gt;threshold&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="nx"&gt;threshold_type&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PERCENTAGE"&lt;/span&gt;
    &lt;span class="nx"&gt;comparison_operator&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"GREATER_THAN"&lt;/span&gt;
    &lt;span class="nx"&gt;subscriber_email_addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"billing-alerts@yourcompany.com"&lt;/span&gt;&lt;span class="p"&gt;]&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;The 80% alert is a second &lt;code&gt;notification&lt;/code&gt; block with &lt;code&gt;ACTUAL&lt;/code&gt; and &lt;code&gt;80&lt;/code&gt;, and if you use AWS credits, add &lt;code&gt;cost_types { include_credit = false }&lt;/code&gt;. The address still has to be confirmed in the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the alerts won't do
&lt;/h2&gt;

&lt;p&gt;AWS Budgets data is &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-managing-costs.html" rel="noopener noreferrer"&gt;refreshed up to three times a day, usually 8–12&amp;nbsp;hours apart&lt;/a&gt;, so an instance started in the evening may only show up in an alert the next day.&lt;/p&gt;

&lt;p&gt;An alert doesn't stop anything either. That is what &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-controls.html" rel="noopener noreferrer"&gt;budget actions&lt;/a&gt; are for: once a threshold is crossed they restrict permissions on the account or stop chosen EC2 and RDS instances, either automatically or after you approve. An automatic action on a production database can easily turn an expensive month into an outage, so in a small company I'd only use actions with manual approval.&lt;/p&gt;

&lt;p&gt;You don't need the older &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html" rel="noopener noreferrer"&gt;CloudWatch billing alarm&lt;/a&gt; in a new setup: a budget does the same job and adds a forecast.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a small team should set up
&lt;/h2&gt;

&lt;p&gt;If a forgotten instance or a Lambda stuck in a loop pushes spend over a threshold, you'll usually see it in an e-mail within a day or two, not on the invoice. When the first alert arrives, open Cost Explorer, group costs by service and set the date range to month-to-date. You'll see which service grew.&lt;/p&gt;

&lt;p&gt;What an alert won't tell you is whether your current bill is too high, because you set the budget at the level you are used to. If costs have been creeping up for months, an &lt;a href="https://codelevel.pl/en/services/aws-cost-audit/" rel="noopener noreferrer"&gt;AWS cost audit&lt;/a&gt; is worth doing.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/aws-budget-alerts-setup/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Data Act ends cloud switching fees on 12 January 2027</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:23:59 +0000</pubDate>
      <link>https://dev.to/codelevel/the-data-act-ends-cloud-switching-fees-on-12-january-2027-e64</link>
      <guid>https://dev.to/codelevel/the-data-act-ends-cloud-switching-fees-on-12-january-2027-e64</guid>
      <description>&lt;p&gt;From 12&amp;nbsp;January 2027 the &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32023R2854" rel="noopener noreferrer"&gt;Data Act bars&lt;/a&gt; cloud providers from charging EU customers switching fees, including data egress charges for moving data to a new provider or to your own servers. Traffic between two clouds you use side by side can still be charged.&lt;/p&gt;

&lt;p&gt;If you are leaving AWS altogether, don't wait for January, because AWS already waives transfer charges on request when you move out. When you move one whole service, such as all of S3, and keep the application on AWS, the ban only helps from 12&amp;nbsp;January. AWS needs the Data Act switching request at least two months before such a switch starts, counted from the day the request is complete, so to start on 12&amp;nbsp;January, send it well before 12&amp;nbsp;November.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Data Act says
&lt;/h2&gt;

&lt;p&gt;The Data Act, Regulation (EU) 2023/2854, has applied since 12&amp;nbsp;September 2025, &lt;a href="https://digital-strategy.ec.europa.eu/en/factpages/data-act-explained" rel="noopener noreferrer"&gt;according to the European Commission&lt;/a&gt;, so you can use its switching procedure now. Until 11&amp;nbsp;January 2027 a provider may charge for a switch, but no more than the costs directly linked to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS's programme for customers who leave
&lt;/h2&gt;

&lt;p&gt;The programme has run since March 2024 and covers every AWS region. &lt;a href="https://aws.amazon.com/blogs/aws/free-data-transfer-out-to-internet-when-moving-out-of-aws/" rel="noopener noreferrer"&gt;According to the AWS post updated on 30&amp;nbsp;September 2025&lt;/a&gt;, you apply through AWS Support, and once the request is approved you get credits for data transfer out to the internet and 90&amp;nbsp;days to finish the move. &lt;a href="https://aws.amazon.com/about-aws/global-infrastructure/global-network/faqs" rel="noopener noreferrer"&gt;AWS's FAQ&lt;/a&gt; still says 60&amp;nbsp;days, so check the term in AWS's reply to your request. According to the FAQ, within that term you delete all remaining data from your account or close it, so you can't keep even backups in S3.&lt;/p&gt;

&lt;p&gt;Outside the AWS programme and outside the Data Act procedure, you pay list price for the transfer. The first &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;100&amp;nbsp;GB a month are free&lt;/a&gt;, and sending 5&amp;nbsp;TB from Frankfurt to the internet in one month costs about $450 at &lt;a href="https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AWSDataTransfer/20260916132208/eu-central-1/index.json" rel="noopener noreferrer"&gt;AWS's list prices of 16&amp;nbsp;September 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Data Act switch works on AWS
&lt;/h2&gt;

&lt;p&gt;If the payer account, the one that pays the bill, has an EU country in its account settings, &lt;a href="https://d1.awsstatic.com/onedam/marketing-channels/website/aws/en_US/legal/approved/eu-data-act-addendum.pdf" rel="noopener noreferrer"&gt;AWS's Data Act addendum&lt;/a&gt; covers it together with every account billed through it. A payer account whose country is outside the EU, the UK included, doesn't qualify. The addendum distinguishes a Complete Switch, which moves all your services, from a Service Switch, which moves one or more whole services while the rest stays on AWS. For S3, a whole service means every bucket on every account under that payer.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The chart for this part is in the &lt;a href="https://codelevel.pl/en/insights/data-act-cloud-switching-fees-2027/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
Once the switch starts, you have a transitional period of 30&amp;nbsp;calendar days to move the data. If AWS finds that technically impossible, it can extend the period to seven months at most. If you copy data before the switch starts, in December for example, you may pay list price for that transfer.&lt;/p&gt;

&lt;p&gt;When the application writes to the new provider and all the data is there, check the copy: compare object counts and checksums, and include older versions in versioned buckets. Then delete the moved service's data from AWS, and only then notify AWS that the switch is complete. The switch ends when AWS receives your notice, at the end of the transitional period at the latest, and the data must be gone from AWS by then. If you don't send the notice or you leave data on AWS, you pay standard rates and have to reimburse AWS for any credits or fee waivers you received for the switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for a small company
&lt;/h2&gt;

&lt;p&gt;Nothing changes on 12&amp;nbsp;January if you stay on AWS and move nothing.&lt;/p&gt;

&lt;p&gt;For a full move off AWS, ask AWS Support to waive the transfer charges before you start copying data. The &lt;a href="https://codelevel.pl/en/calculator/" rel="noopener noreferrer"&gt;hosting cost calculator&lt;/a&gt; estimates what you will pay at Hetzner or OVH. Savings Plans, Reserved Instances and any minimum spend in your AWS agreement still apply after you leave, which is why I check them first when I draw up a &lt;a href="https://codelevel.pl/en/services/cloud-exit/" rel="noopener noreferrer"&gt;cloud exit plan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If the application and its data are to stay split across two clouds, &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32023R2854" rel="noopener noreferrer"&gt;Article&amp;nbsp;34 of the regulation&lt;/a&gt; lets providers go on charging for the traffic between them after 12&amp;nbsp;January 2027, at no more than what the traffic costs them.&lt;/p&gt;

&lt;p&gt;The date matters most when you want to move all of S3 and keep the application on AWS. If the move can wait, set the Service Switch to start on 12&amp;nbsp;January 2027 or later. If AWS only receives the complete request on 1&amp;nbsp;December, the switch starts on 1&amp;nbsp;February at the earliest.&lt;/p&gt;

&lt;p&gt;Just make sure nothing stays in S3. A single bucket with logs or Terraform state is enough to make it something other than a Service Switch, and then you pay list price for the transfer.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/data-act-cloud-switching-fees-2027/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>hetzner</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>What EC2-Other means on your AWS bill</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Mon, 12 Oct 2026 07:05:38 +0000</pubDate>
      <link>https://dev.to/codelevel/what-ec2-other-means-on-your-aws-bill-466a</link>
      <guid>https://dev.to/codelevel/what-ec2-other-means-on-your-aws-bill-466a</guid>
      <description>&lt;p&gt;EC2-Other is the Cost Explorer line where AWS puts EC2 charges other than instance hours. &lt;a href="https://aws.amazon.com/blogs/aws-cloud-financial-management/optimize-and-save-on-the-other-services" rel="noopener noreferrer"&gt;According to the AWS cost management blog&lt;/a&gt;, it holds EBS volumes and their snapshots, NAT gateways, some of your data transfer and a few smaller fees.&lt;/p&gt;

&lt;p&gt;To see what makes up that amount, &lt;a href="https://repost.aws/knowledge-center/ebs-understand-billing-information" rel="noopener noreferrer"&gt;filter Cost Explorer to Service = EC2-Other and group the result by Usage type&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Breaking down EC2-Other in Cost Explorer
&lt;/h2&gt;

&lt;p&gt;Open Cost Explorer in the Billing and Cost Management console and set the range to the last six months by month, so you can see which part is growing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cur/latest/userguide/cur-data-transfers-charges.html" rel="noopener noreferrer"&gt;Outside us-east-1&lt;/a&gt;, usage types start with a Region code: &lt;code&gt;EUC1-&lt;/code&gt; in Frankfurt. The main usage types in EC2-Other:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Usage type&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;What to check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EBS:VolumeUsage.gp2 and .gp3&lt;/td&gt;
&lt;td&gt;Provisioned volume storage&lt;/td&gt;
&lt;td&gt;Unattached volumes and gp2 volumes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EBS:SnapshotUsage&lt;/td&gt;
&lt;td&gt;Volume snapshots&lt;/td&gt;
&lt;td&gt;Snapshots of deregistered AMIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NatGateway-Hours&lt;/td&gt;
&lt;td&gt;NAT gateway hours&lt;/td&gt;
&lt;td&gt;Number of gateways&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NatGateway-Bytes&lt;/td&gt;
&lt;td&gt;Data processed by NAT&lt;/td&gt;
&lt;td&gt;Traffic to S3 and DynamoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DataTransfer-Regional-Bytes&lt;/td&gt;
&lt;td&gt;Traffic between Availability Zones&lt;/td&gt;
&lt;td&gt;Services that talk across zones&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Public IPv4 addresses, which older AWS posts list under EC2-Other, now sit under &lt;a href="https://aws.amazon.com/vpc/pricing/" rel="noopener noreferrer"&gt;the VPC service&lt;/a&gt;. Since 1 February 2024 each one costs &lt;a href="https://aws.amazon.com/blogs/aws/new-aws-public-ipv4-address-charge-public-ip-insights/" rel="noopener noreferrer"&gt;about $3.65 a month&lt;/a&gt;, even when nothing uses it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Volumes and snapshots
&lt;/h2&gt;

&lt;p&gt;You pay for the gigabytes a volume has provisioned, even while the instance is stopped. When you terminate an instance, AWS &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html" rel="noopener noreferrer"&gt;deletes only the root volume by default&lt;/a&gt;, so any other volumes stay in the &lt;code&gt;available&lt;/code&gt; state and keep costing money. How to list them, and when it pays to move from gp2 to gp3, is in my &lt;a href="https://codelevel.pl/en/insights/what-i-check-in-an-aws-cost-audit/" rel="noopener noreferrer"&gt;AWS cost audit checklist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/deregister-ami.html" rel="noopener noreferrer"&gt;Deregistering an AMI&lt;/a&gt; leaves its snapshots in place by default, so you keep paying for them. When you deregister, tick "Delete associated snapshots" in the console or add &lt;code&gt;--delete-associated-snapshots&lt;/code&gt; to &lt;code&gt;aws ec2 deregister-image&lt;/code&gt;. A snapshot made together with an image has a description like &lt;code&gt;Created by CreateImage(i-…) for ami-…&lt;/code&gt;, so you can check whether that image still exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  NAT gateways
&lt;/h2&gt;

&lt;p&gt;A NAT gateway is the part of the network that lets servers without a public address reach the internet, for example to download updates. You pay for &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-pricing.html" rel="noopener noreferrer"&gt;every hour it runs&lt;/a&gt;, even when no traffic goes through it, and separately for every GB it processes.&lt;/p&gt;

&lt;p&gt;If NatGateway-Hours dominates, count your gateways. A test environment usually manages with one per VPC. In production, AWS &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/nat-gateway-pricing.html" rel="noopener noreferrer"&gt;recommends&lt;/a&gt; keeping the gateway in the same zone as the resources that send a lot of data through it, because &lt;a href="https://www.repost.aws/knowledge-center/vpc-reduce-nat-gateway-transfer-costs" rel="noopener noreferrer"&gt;you then avoid cross-zone transfer charges&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When NatGateway-Bytes is the bigger cost, find out where the traffic goes. Traffic to S3 and DynamoDB in the same Region can go through a free &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/gateway-endpoints.html" rel="noopener noreferrer"&gt;gateway endpoint&lt;/a&gt;. Once you associate it with the route tables of your private subnets, that traffic stops passing through the NAT gateway. Check your bucket policies first: a condition on the gateway's address in &lt;code&gt;aws:SourceIp&lt;/code&gt; will stop letting that traffic in, because &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html" rel="noopener noreferrer"&gt;the key is absent for requests through a VPC endpoint&lt;/a&gt;, so replace it with an &lt;code&gt;aws:SourceVpce&lt;/code&gt; condition.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means for a small team
&lt;/h2&gt;

&lt;p&gt;Start with the usage type that grows month after month while your application's traffic stays flat. If it is NatGateway-Bytes and the application keeps files in S3, add an S3 endpoint first. If it is VolumeUsage or SnapshotUsage, start with the list of &lt;code&gt;available&lt;/code&gt; volumes and delete only the ones you are sure nobody needs. If in doubt, take a snapshot first.&lt;/p&gt;

&lt;p&gt;Rather than clicking through Cost Explorer, you can load an export of the whole bill grouped by Usage type, without the service filter, into the &lt;a href="https://codelevel.pl/en/calculator/csv-analysis/" rel="noopener noreferrer"&gt;CSV analysis&lt;/a&gt;. The file never leaves your browser, and the analysis shows NAT gateways, traffic between zones, snapshots and gp2 volumes separately when they are a significant part of the bill.&lt;/p&gt;

&lt;p&gt;If EC2-Other is a large share of the bill and the usage type split does not explain it, I can go through the account as part of an &lt;a href="https://codelevel.pl/en/services/aws-cost-audit/" rel="noopener noreferrer"&gt;AWS cost audit&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/ec2-other-aws-bill/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>What I check in an AWS cost audit</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Mon, 12 Oct 2026 05:05:22 +0000</pubDate>
      <link>https://dev.to/codelevel/what-i-check-in-an-aws-cost-audit-2ebc</link>
      <guid>https://dev.to/codelevel/what-i-check-in-an-aws-cost-audit-2ebc</guid>
      <description>&lt;p&gt;In an AWS cost audit I start with six places: EC2 instance size, Savings Plans, EBS volumes, public IPv4 addresses, NAT Gateway and CloudWatch logs. Five of them are resources left over from a test or still running on their defaults. The sixth is a discount for steady load that nobody has taken.&lt;/p&gt;

&lt;p&gt;You can see each of them yourself. Open Cost Explorer, set the last three months and group costs by Usage type. The usage types are in the table, and Savings Plans have a separate report, described below. In Frankfurt, usage types carry the prefix &lt;code&gt;EUC1-&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you check&lt;/th&gt;
&lt;th&gt;Usage type in Cost Explorer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EC2 instances&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BoxUsage:&amp;lt;instance type&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Volumes and snapshots&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;EBS:VolumeUsage.gp2&lt;/code&gt;, &lt;code&gt;EBS:SnapshotUsage&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IPv4 addresses&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PublicIPv4:IdleAddress&lt;/code&gt;, &lt;code&gt;PublicIPv4:InUseAddress&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NAT Gateway&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;NatGateway-Hours&lt;/code&gt;, &lt;code&gt;NatGateway-Bytes&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CloudWatch logs&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;DataProcessing-Bytes&lt;/code&gt;, &lt;code&gt;TimedStorage-ByteHrs&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You can also load a Cost Explorer export into the &lt;a href="https://codelevel.pl/en/calculator/csv-analysis/" rel="noopener noreferrer"&gt;CSV analysis&lt;/a&gt;, which flags most of these. The file stays in your browser. The prices below are on-demand rates in Frankfurt according to AWS pricing on 8&amp;nbsp;October 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  EC2 instances bigger than the traffic needs
&lt;/h2&gt;

&lt;p&gt;An instance is usually sized at launch, with headroom, and nobody looks at it again. Turn on Compute Optimizer in the AWS console. It is &lt;a href="https://aws.amazon.com/compute-optimizer/pricing/" rel="noopener noreferrer"&gt;free&lt;/a&gt; and uses the last 14&amp;nbsp;days of metrics to show which instances are too big. It only takes memory into account when the &lt;a href="https://docs.aws.amazon.com/compute-optimizer/latest/ug/ec2-metrics-analyzed.html" rel="noopener noreferrer"&gt;CloudWatch agent&lt;/a&gt; runs on the instance.&lt;/p&gt;

&lt;p&gt;Also check whether the application would run on Graviton, AWS's own ARM processors. In Frankfurt an m7g.large with Graviton is &lt;a href="https://aws.amazon.com/ec2/pricing/on-demand/" rel="noopener noreferrer"&gt;19% cheaper&lt;/a&gt; than an m7i.large with an Intel processor. Resizing means &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/change-instance-type-of-ebs-backed-instance.html" rel="noopener noreferrer"&gt;stopping the instance&lt;/a&gt;, but you cannot move to ARM by changing the type alone. You need &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/resize-limitations.html" rel="noopener noreferrer"&gt;a new instance from an arm64 image&lt;/a&gt;, and for containers an arm64 build in CI as well.&lt;/p&gt;

&lt;p&gt;A test environment often runs around the clock while the team uses it ten hours a day, Monday to Friday: 50 of the 168 hours in a week. AWS's &lt;a href="https://aws.amazon.com/solutions/implementations/instance-scheduler-on-aws/" rel="noopener noreferrer"&gt;Instance Scheduler&lt;/a&gt; starts and stops EC2 and RDS on a schedule you assign to the instance with a tag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Always-on servers billed on demand
&lt;/h2&gt;

&lt;p&gt;If some instances have run non-stop for months and you pay the on-demand rate for them, you are paying more than you need to. Compute Savings Plans cut the rate by &lt;a href="https://aws.amazon.com/savingsplans/compute-pricing/" rel="noopener noreferrer"&gt;up to 66%&lt;/a&gt; in exchange for a one- or three-year commitment.&lt;/p&gt;

&lt;p&gt;In Cost Explorer, open Savings Plans and then the Coverage report. It shows &lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ce/get-savings-plans-coverage.html" rel="noopener noreferrer"&gt;how much of your cost a plan covers&lt;/a&gt;. Buy a plan only for the capacity that always runs, and only after you have downsized the instances. Buy it earlier and you commit to paying for the headroom for the whole term.&lt;/p&gt;

&lt;h2&gt;
  
  
  gp2 volumes, orphaned volumes and old snapshots
&lt;/h2&gt;

&lt;p&gt;In Frankfurt a gp3 volume is &lt;a href="https://aws.amazon.com/ebs/pricing/" rel="noopener noreferrer"&gt;20% cheaper&lt;/a&gt; than gp2, and you can change the type &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/requesting-ebs-volume-modifications.html" rel="noopener noreferrer"&gt;without detaching the volume&lt;/a&gt;. Large gp2 volumes are faster than gp3 at its base price, though: from 334&amp;nbsp;GiB they have &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html" rel="noopener noreferrer"&gt;twice the throughput&lt;/a&gt;, and above 1,000&amp;nbsp;GiB more IOPS. For those volumes, buy the missing performance on gp3, or the disk will slow down.&lt;/p&gt;

&lt;p&gt;A volume in the &lt;code&gt;available&lt;/code&gt; state &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/ebs-describing-volumes.html" rel="noopener noreferrer"&gt;is not attached to any instance&lt;/a&gt;, and you pay for it all the same. The command works in one region, so run it with &lt;code&gt;--region&lt;/code&gt; for each one you use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-volumes &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;status,Values&lt;span class="o"&gt;=&lt;/span&gt;available &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"Volumes[].[VolumeId,Size,VolumeType,CreateTime]"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before deleting a volume, take a snapshot of it. It costs &lt;a href="https://aws.amazon.com/ebs/pricing/" rel="noopener noreferrer"&gt;$0.054 per GB-month&lt;/a&gt;, less than the volume, and lets you restore the data.&lt;/p&gt;

&lt;p&gt;Snapshots pile up when a backup script creates copies and never deletes any. Replace the script with a &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/snapshot-lifecycle.html" rel="noopener noreferrer"&gt;Data Lifecycle Manager&lt;/a&gt; policy that deletes old copies itself. Delete the script's older copies by hand, because DLM does not touch them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Public IPv4 addresses
&lt;/h2&gt;

&lt;p&gt;Since February 2024 AWS has charged &lt;a href="https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonVPC/20260917190528/eu-central-1/index.json" rel="noopener noreferrer"&gt;$3.65 a month&lt;/a&gt; for every public IPv4 address, including one attached to a running instance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IdleAddress&lt;/code&gt; on the bill means addresses nothing is using. Release each one that is not in DNS or on a customer's or supplier's allowlist. The free &lt;a href="https://aws.amazon.com/blogs/aws/new-aws-public-ipv4-address-charge-public-ip-insights/" rel="noopener noreferrer"&gt;Public IP Insights&lt;/a&gt; shows what each address is attached to. An instance behind a load balancer rarely needs its own public IP. If it connects to the internet itself, though, without an address it will need a NAT gateway, which costs more than ten addresses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Traffic through NAT Gateway
&lt;/h2&gt;

&lt;p&gt;A NAT gateway is the gateway through which servers without a public address reach the internet. In Frankfurt it costs &lt;a href="https://aws.amazon.com/vpc/pricing/" rel="noopener noreferrer"&gt;about $38 a month&lt;/a&gt;, plus $0.052 for every GB that passes through it. When such a server reads and writes files in S3, all of that traffic goes through the gateway by default.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;NatGateway-Bytes&lt;/code&gt; costs more than &lt;code&gt;NatGateway-Hours&lt;/code&gt;, find out where the application sends its traffic. Traffic to S3 and DynamoDB in the same region can go through a gateway endpoint, which &lt;a href="https://docs.aws.amazon.com/vpc/latest/privatelink/gateway-endpoints.html" rel="noopener noreferrer"&gt;AWS does not charge for&lt;/a&gt;. It is a route table entry, so the application code stays as it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  CloudWatch logs
&lt;/h2&gt;

&lt;p&gt;In Frankfurt ingesting a gigabyte of logs costs &lt;a href="https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonCloudWatch/20261007115540/eu-central-1/index.json" rel="noopener noreferrer"&gt;$0.63&lt;/a&gt;, and CloudWatch Logs &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html" rel="noopener noreferrer"&gt;keeps log data indefinitely by default&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the CloudWatch console, open Log groups and sort by size. For groups showing Never Expire in the Retention column, set the period you actually need, for example 30&amp;nbsp;days for application logs. If &lt;code&gt;DataProcessing-Bytes&lt;/code&gt; costs more than &lt;code&gt;TimedStorage-ByteHrs&lt;/code&gt;, reduce the volume of logging in the application itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do this week
&lt;/h2&gt;

&lt;p&gt;Create a budget in AWS Budgets with an e-mail alert. &lt;a href="https://aws.amazon.com/aws-cost-management/aws-budgets/pricing/" rel="noopener noreferrer"&gt;Budgets and their notifications are free&lt;/a&gt;, and the alert arrives when actual or forecast spend for the month crosses the amount you set. After that, activate your environment tags as &lt;a href="https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html" rel="noopener noreferrer"&gt;cost allocation tags&lt;/a&gt; so Cost Explorer can separate staging from production.&lt;/p&gt;

&lt;p&gt;Leave changes to instances, volumes and NAT with a developer, because each one needs testing. The &lt;a href="https://codelevel.pl/en/services/aws-cost-audit/sample-report/" rel="noopener noreferrer"&gt;sample report&lt;/a&gt; shows the result: a list of such changes, each with its monthly amount. It uses sample data that does not come from any client.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/what-i-check-in-an-aws-cost-audit/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>RDS has been charging extra for MySQL 8.0 since August</title>
      <dc:creator>CODELEVEL - Jacob Binczyk</dc:creator>
      <pubDate>Thu, 08 Oct 2026 13:27:27 +0000</pubDate>
      <link>https://dev.to/codelevel/rds-has-been-charging-extra-for-mysql-80-since-august-568j</link>
      <guid>https://dev.to/codelevel/rds-has-been-charging-extra-for-mysql-80-since-august-568j</guid>
      <description>&lt;p&gt;Standard support for MySQL 8.0 on RDS &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html" rel="noopener noreferrer"&gt;ended on 31 July 2026&lt;/a&gt;. Since 1 August AWS has been adding an &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support-overview.html" rel="noopener noreferrer"&gt;Extended Support&lt;/a&gt; charge to every such database that has it enabled. The API, the CLI and Terraform &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support-creating-db-instance.html" rel="noopener noreferrer"&gt;enable it by default&lt;/a&gt;; in the console you have to tick it. The charge is already on your August and September bills.&lt;/p&gt;

&lt;p&gt;If you run MySQL 8.0, move it to 8.4, which has standard support &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html" rel="noopener noreferrer"&gt;until 31 July 2029&lt;/a&gt;. Aurora MySQL 3, the 8.0-compatible line, has standard support &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraMySQLReleaseNotes/AuroraMySQL.release-calendars.html" rel="noopener noreferrer"&gt;until 30 April 2028&lt;/a&gt;, so there is no surcharge there yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Extended Support costs
&lt;/h2&gt;

&lt;p&gt;In Frankfurt, the &lt;a href="https://pricing.us-east-1.amazonaws.com/offers/v1.0/aws/AmazonRDS/20261006224050/eu-central-1/index.json" rel="noopener noreferrer"&gt;AWS price list on 6 October 2026&lt;/a&gt; gives $0.122 per vCPU-hour for the first two years, which is about $89 a month for each vCPU. From 1 August 2028 the rate doubles to $0.244. A Multi-AZ database keeps a standby copy in a second zone, and AWS &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support-charges.html" rel="noopener noreferrer"&gt;charges for that standby too&lt;/a&gt;, so you pay twice as much.&lt;/p&gt;

&lt;p&gt;Take a db.m6g.large in Multi-AZ, with 2 vCPUs. The instance alone costs about $264 a month in Frankfurt, and Extended Support adds $356 on top. For August and September AWS has already added about $714 to that database.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The chart for this part is in the &lt;a href="https://codelevel.pl/en/insights/mysql-8-rds-extended-support-charges/" rel="noopener noreferrer"&gt;original post&lt;/a&gt;.&lt;/em&gt;&lt;br&gt;
Reserved Instances won't reduce the surcharge, because &lt;a href="https://aws.amazon.com/blogs/aws-cloud-financial-management/estimating-the-charges-for-amazon-rds-extended-support/" rel="noopener noreferrer"&gt;RI discounts don't apply to Extended Support&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where it shows on the bill
&lt;/h2&gt;

&lt;p&gt;Extended Support is a &lt;a href="https://aws.amazon.com/blogs/aws-cloud-financial-management/estimating-the-charges-for-amazon-rds-extended-support/" rel="noopener noreferrer"&gt;separate line item on the bill&lt;/a&gt;, next to instance hours and storage. In Cost Explorer, type &lt;code&gt;ExtendedSupport&lt;/code&gt; into the Usage Type filter and select every result. The Frankfurt usage type for MySQL 8.0 is &lt;code&gt;EUC1-ExtendedSupport:Yr1-Yr2:MySQL8.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The same filter catches databases on older versions too. MySQL 5.7 &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html" rel="noopener noreferrer"&gt;has been billed at the year-three rate&lt;/a&gt; since 1 March 2026. You can also load a Cost Explorer export grouped by usage type into the &lt;a href="https://codelevel.pl/en/calculator/csv-analysis/" rel="noopener noreferrer"&gt;CSV analysis&lt;/a&gt;, which lists the largest items on the bill.&lt;/p&gt;

&lt;p&gt;To see which databases you are paying for, run this command in each region:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds describe-db-instances &lt;span class="nt"&gt;--region&lt;/span&gt; eu-central-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"DBInstances[?Engine=='mysql'].[
    DBInstanceIdentifier,
    EngineVersion, MultiAZ,
    EngineLifecycleSupport]"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any 8.0.x row with &lt;code&gt;open-source-rds-extended-support&lt;/code&gt; in the last column is a database you are paying the surcharge on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching it off means an upgrade
&lt;/h2&gt;

&lt;p&gt;You can change &lt;code&gt;EngineLifecycleSupport&lt;/code&gt; at any time. But if you disable Extended Support on an 8.0 database, &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support-overview.html" rel="noopener noreferrer"&gt;RDS upgrades it automatically&lt;/a&gt; to the next supported version, 8.4, whether or not you have tested the application on it. The charge &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/extended-support-charges.html" rel="noopener noreferrer"&gt;stops&lt;/a&gt; once the database reaches a supported version. I described the same mechanism for &lt;a href="https://codelevel.pl/en/insights/postgresql-14-end-of-life-november-2026/" rel="noopener noreferrer"&gt;PostgreSQL 14&lt;/a&gt;, where the deadline is still ahead.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to move to 8.4
&lt;/h2&gt;

&lt;p&gt;The target is 8.4, because newer MySQL versions are only available on RDS in the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html" rel="noopener noreferrer"&gt;Database Preview&lt;/a&gt; environment, which AWS does not allow for production.&lt;/p&gt;

&lt;p&gt;AWS &lt;a href="https://aws.amazon.com/blogs/database/amazon-rds-for-mysql-lts-version-8-4-is-now-generally-available/" rel="noopener noreferrer"&gt;recommends a blue/green deployment&lt;/a&gt;. RDS builds a copy of the database and replicates production changes into it, and you upgrade the copy to 8.4 and test the application against it. The copy is &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html" rel="noopener noreferrer"&gt;read-only&lt;/a&gt; and should stay that way, because writes to it break replication and can end up in production after the switch-over. Run tests that write against a database restored from a snapshot.&lt;/p&gt;

&lt;p&gt;The switch-over itself usually takes under a minute. Afterwards the old database stays as &lt;code&gt;…-old1&lt;/code&gt;, still on 8.0, and &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-considerations.html" rel="noopener noreferrer"&gt;AWS keeps charging for the instance&lt;/a&gt; and for Extended Support. Delete it once you no longer need a way back.&lt;/p&gt;

&lt;p&gt;An in-place upgrade takes &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.MySQL.Major.html" rel="noopener noreferrer"&gt;about 10 minutes&lt;/a&gt;, and the database is down for that time. The documentation describes no way back to 8.0 after a successful upgrade.&lt;/p&gt;

&lt;p&gt;On the copy, read &lt;code&gt;PrePatchCompatibility.log&lt;/code&gt;: &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_UpgradeDBInstance.MySQL.Major.html" rel="noopener noreferrer"&gt;RDS runs prechecks before it stops the database&lt;/a&gt; and cancels the upgrade if any of them fail. Then check the changes listed in &lt;a href="https://aws.amazon.com/blogs/database/amazon-rds-for-mysql-lts-version-8-4-is-now-generally-available/" rel="noopener noreferrer"&gt;AWS's announcement of MySQL 8.4 on RDS&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New users in 8.4 get the &lt;code&gt;caching_sha2_password&lt;/code&gt; plugin by default, while existing ones keep &lt;code&gt;mysql_native_password&lt;/code&gt;. Make sure the application can connect with an account created after the upgrade.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;restrict_fk_on_non_standard_key&lt;/code&gt; is on by default and stops you creating foreign keys built on non-unique or partial keys. Check that your schema migrations don't create any.&lt;/li&gt;
&lt;li&gt;The old replication statements are syntax errors in 8.4, so in scripts and monitoring replace &lt;code&gt;SHOW MASTER STATUS&lt;/code&gt; with &lt;code&gt;SHOW BINARY LOG STATUS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Compare the timing of your heaviest queries, because 8.4 changes InnoDB defaults.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  When to do it
&lt;/h2&gt;

&lt;p&gt;Ideally in October 2026. On the example db.m6g.large, every month of delay costs about $356. If the account has several 8.0 databases, start with the largest by vCPU count, standby included, since the charge scales with it.&lt;/p&gt;

&lt;p&gt;Move anything on Aurora MySQL 3 to Aurora MySQL 8.4 during 2027, ahead of the 30 April 2028 deadline.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://codelevel.pl/en/insights/mysql-8-rds-extended-support-charges/" rel="noopener noreferrer"&gt;codelevel.pl&lt;/a&gt;. Prices are net, for businesses. AWS, Hetzner and OVH are trademarks of their owners; CODELEVEL is not a partner, reseller or representative of any of them.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>finops</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
