A web page beside a teal speed gauge with its needle far to the right, and a magnifying glass over a folder with a coral dot.

How we made ShopClass 7.0 faster than 6.x, and what went wrong on the way

On a real site with 245,000 listings, ShopClass 7.0 serves 45% more pages a second than 6.4. How we found the slow parts, and the folder that surprised us.

ShopClass started as our Osclass code. When we renamed it to ShopClass with 6.0 in August 2026, it was already faster than our older Osclass 5.x releases. By 6.4 it was also faster than the other big open-source classifieds apps. We tested them side by side, and you can read how ShopClass relates to Osclass.

We could have stopped there. But we want ShopClass to be the best classifieds script, with performance at its core. So we never stop improving our own code, tuning the database structure, and using newer tools in the way we deploy. That is what kept me going for 7.0.

Each fix took away work

The method was simple. Run a load test, count what one page does, remove what it does not need, and run the test again.

With each fix, the numbers moved the right way. Fewer queries per page. Less CPU spent on things the page did not need.

A few examples:

  1. One query instead of twelve. The home page asked the database about paid upgrades once for every listing card. We changed it to one query for all of them, and the home page went from 438 to 587 requests a second. That one shipped in 6.4.0.
  2. Less data from the cache. On a copy of TuffClassified, every home page read 946 KB from Valkey, and PHP had to unpack all of it. Now each PHP worker keeps a short copy of that data in APCu, so the home page reads 7 KB instead. This was the biggest gain in 7.0. You turn it on with OSC_CACHE_LOCAL=1.
  3. Kept connections. Every page used to open a new database connection and a new Valkey connection. Now a worker can keep them open. New database connections went from one per page to 5 per 356 pages.
  4. Smaller theme data. Our theme kept its popular links as 110 KB in the cache. With the new osc_cache_remember() helper it keeps about 1 KB.

Valkey calls per page went from about 16 to 5.

On the real site

TuffClassified.com is our own classifieds site in India, with about 245,000 listings. It has run every ShopClass release, and our Osclass releases before that. New code goes there first, before we release it to everyone.

We ran a k6 load test against the live site with the page cache off, so PHP built every page. We counted how many pages a second it could serve while the slowest 5% stayed under 500 ms:

Step Pages a second
ShopClass 6.4 225
ShopClass 7.0 core changes 275
Theme on osc_cache_remember(), and the front proxy reusing connections 327

The proxy change in the last row is our own server setup, not ShopClass. So 327 is not all 7.0.

The folder that surprised me

After all this, I ran our small side-by-side test before the release: 7.0 against 6.4.7. The gains were shrinking. 7.0 was even slower than 6.4.7: by 14% on the home page, and by 10% on search.

That made no sense. Every fix had been measured on its own, and each one had helped.

First I checked the test machine. It was a shared droplet, and two rounds of the same test could differ by up to 20%. So I moved to a DigitalOcean CPU-Optimized droplet, where the CPU cores are not shared. Two rounds now came within 2%. 7.0 was still slower.

So I counted the queries again. A few of them did not belong on a home page at all. They were checking the cron schedule, on every page view.

The cause was not in the code. I had copied the 7.0 files to the test box as my own user, so PHP could not write to the uploads folder. ShopClass keeps a small file there to note when cron last ran. It could not update it, so it ran the cron check on every page instead of once every 5 minutes.

I fixed the folder owner, and 7.0 was faster on every page:

Version Home Listing Search
ShopClass 6.4.7, no cache 125 80 101
ShopClass 7.0, no cache 137 107 112
ShopClass 7.0, Valkey and the worker copy 204 136 178

ShopClass now handles that case too. When it cannot write to the uploads folder, it keeps the cron file in the system temp folder.

It is still worth checking on your own server, because photos are saved in that folder too. On Debian or Ubuntu, PHP usually runs as www-data. From your ShopClass folder:

Terminal window
sudo -u www-data test -w oc-content/uploads && echo "PHP can write here"

If it prints nothing, fix the owner:

Terminal window
sudo chown -R www-data:www-data oc-content/uploads

Keep digging

If you are serious about performance, I think you have to look past the obvious places. A faster database or a newer PHP version alone will not fix everything. Our biggest cost was not a slow query. It was moving cached data around. And our strangest slowdown was not code at all. It was a folder owner.

So keep digging, and count what each page really does.

Turning it on

Many ShopClass sites run on shared hosting. There, APCu can be shared between sites, so the worker copy is not safe to turn on for everyone. Kept database connections also need a database that allows enough connections for every worker. So both stay off until you turn them on. Our Docker image turns on the worker copy for you.

On a VPS or Docker, this is what TuffClassified uses:

Terminal window
OSC_CACHE=redis
OSC_CACHE_LOCAL=1
OSC_DB_PERSISTENT=1

The cache docs explain each setting, and the Docker guide covers the image.

If you measure your own site before and after, I would like to see the numbers. Found something? Open an issue on GitHub.