Hi, I’m Luis

I build and run the platform under Magento and Adobe Commerce stores: the infrastructure, the release pipeline, and the tooling that proves a deploy worked before a customer finds out it didn’t. I’ve been working in Magento since the 1.x days.

Most of my day is PHP, Python and Ansible. I’m ramping up in Go, Rust and Ruby.

Every Magento login downloads every country on earth

On 7 September we went looking at customer/section/load on a stock Magento 2.4.8 store with the sample data. It’s the request that fills in everything a cached page can’t know about you: your name, your cart count, your messages. It can never be cached, so every call boots the whole application. One response was 61,194 bytes. About 59 KB of that was directory-data: every country and every region the store knows. The same list for every visitor on the planet, travelling through the one channel in Magento that exists because responses can’t be shared. ...

September 24, 2026 · 5 min · Luis Tineo

How many PHP workers? Rereading my 2012 PHP-FPM config

Nine days after the Varnish post, in July 2012, I wrote PHP Offloading… Nginx helps so much!. It explains why nginx beats Apache for Magento (“we are all about performance aren’t we?”), then hands over an nginx server block and a PHP-FPM pool with “of course suggestions are welcome”. Fourteen years on, here are mine. The pool starts like this: pm = dynamic pm.max_children = 50 pm.start_servers = 5 pm.min_spare_servers = 5 pm.max_spare_servers = 50 pm.max_requests = 500 Fifty. The post never says where 50 came from, and that one number decides whether the box runs flat out or falls over. So this is mostly about how to pick it, with two things the rest of that config got quietly wrong along the way. ...

September 24, 2026 · 7 min · Luis Tineo

Rereading my 2012 nginx config: the block that runs your uploads

The PHP-FPM reread ended on a promise. The same July 2012 post, PHP Offloading… Nginx helps so much!, hands over an nginx server block, and one location in it has a problem that has nothing to do with performance: location ~ .php$ { ## Execute PHP scripts if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss ... fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; ... } “Execute PHP scripts” is exactly what it does. Any request ending in .php goes to PHP-FPM, and PHP-FPM runs whatever file nginx names. Nobody asks whether that file was ever meant to be a script. So if somebody can get a .php file into a folder the web server serves, through an avatar upload, an import, a product image field that checks the extension a bit too loosely, that file runs. ...

September 24, 2026 · 3 min · Luis Tineo

Rereading my 2012 Varnish post

In July 2012 I wrote a post called Varnish implementation hints and good to know. It opens with “Sharing knowledge is always a good idea,” and then shares, in order: a set of bash aliases that switch Varnish on and off with iptables, a header that tells PHP whether Varnish is in front, a cookie-stripping regex, a one-line purge, and what it calls “a favorite of mine”, a function that walks every URL in the sitemap so you can clear them all. ...

September 24, 2026 · 4 min · Luis Tineo

The dry run that checked nothing

On 7 September we wrote a script to bring every repository on our GitHub account to the same settings: branch protection, secret scanning, the files a public repository should have. It had a dry-run flag. Run with it, the script said: every repository in scope already conforms It had checked none of them. getopts stops at the first word The script took a subcommand and then flags: apply -n. It parsed the flags with getopts, bash’s built-in option parser, which reads arguments from the front and stops at the first one that doesn’t start with a dash. The first argument was apply. So getopts stopped there and never saw -n. ...

September 24, 2026 · 5 min · Luis Tineo

Two loops waiting for themselves

“are these tasks still running?” I asked that on 2 September, about two background jobs Claude had started, which had been sitting at “Running” for 94 minutes. They were waiting for a Flatpak SDK to finish installing. It had finished at about the four-minute mark. Nothing had failed. They were waiting for themselves Both loops tested for the install with pgrep -f "flatpak install", and were written to stop once nothing matched. pgrep -f searches the whole command line of every process. It leaves itself out of the results, but not the shell that called it, and that shell’s command line held the entire loop. So each loop found itself, and each found the other. They were waiting for their own exit. ...

September 24, 2026 · 4 min · Luis Tineo

The SRE bot I wrote in 2021 is now public

Most monitoring systems tend to answer whether the server is up or not. All of that can be green while an ecommerce checkout is broken, the cart page could even respond 200s, while the add-to-cart button does nothing, and the graphs stay flat because nothing crashed. In November 2021 I wrote a little bot to answer the other question. Every five minutes it opens a real browser, searches for a product, adds it to the cart and loads checkout, and confirms that under the conditions at the time, checkout is up. ...

September 16, 2026 · 6 min · Luis Tineo

From a 2015 docker-compose file to Kapelos

In 2015, at BuyerQuest, I wrote a docker-compose file that ran Magento on my computer. I took it with me to Anatta, and then to Scrubs & Beyond. This week it became Kapelos, a public project anyone can clone. Most of the file changed over those years. What I built it for never did: one Magento store, on one computer, from a file I can read top to bottom. The oldest copy I still have The oldest version I still have is from March 2019. It’s Compose format 2.2, with thirteen services: ...

September 11, 2026 · 5 min · Luis Tineo

Zend Queue with Magento

By using Zend Queue with magento we can create an event driven asynchronus integration system. Just think about how much work you will offload from Magento when integrating with other systems and Magento itself. To keep things simple, let’s pretend that you send emails to your customers everytime a new product gets added. Usually these products get added during the day which also happens to be when your customers are most active buying in the site. An alert about a new product is very important but you don’t want to bug down your email server. That’s where Zend Queue comes to the rescue. In this example I am using mysql to store the queue. If you follow the same example remember to create the tables first, these can be found under: lib/Zend/Queue/Adapter/Db/mysql.sql ...

August 1, 2012 · 2 min · Luis Tineo

Cloning magento modules

Cloning magento modules will never this easy again. Today I wanted (read was forced) to create a module based on one of Magento’s core. Literally I needed to clone some of the Magento modules and while the copy and paste is simple stuff, going class by class and file by file renaming and configuring files is not joke. So why do I need to clone it instead of just doing the usual OOP stuff Magento is so good at? Simply because the functionality is really different in most files and settings. So creating a payment method or paygate or giftcard module is easier when you have an skeleton to work with. Think about it, how different is paying with PayPal from Google Checkout? Functionality wise not that much, essentially they do the same thing but implement it differently. ...

August 1, 2012 · 3 min · Luis Tineo