Case studies

Five problems, and how each one was actually diagnosed.

Every number here comes from live client work and was checked before and after. Where the useful finding was that a client should spend less rather than more, that is included too, because those are usually the ones worth reading.

Verified on live sitesBefore and after evidenceFlagship client named on request
01
Security, edge mitigation

A login page taking half the traffic on the site

The problem

The site felt slow and the obvious next step, the one that had already been suggested, was to pay for a bigger server. Before agreeing to that we looked at what the traffic was actually made of.

The diagnosis

Live server log analysis showed /wp-login.php absorbing about 46% of every request reaching the origin. That is a brute force attack running at 21,626 hits a day. But the second finding mattered just as much: the server was sitting at 7.5% CPU. The attack was noisy, not heavy. It was not what was making the site feel slow.

The fix

We put a Cloudflare Managed Challenge in front of the login path with a skip rule allowlisting the admin IP, so the attack got stopped at the edge without locking out the person who needs to log in.

The result

Hostile traffic dropped to zero within fifteen minutes, verified in the logs, with legitimate admin access confirmed working. Just as valuable, the client did not spend money upgrading a server that was running at 7.5% load. A misdiagnosis there would have cost real money every month and fixed nothing.

02
Infrastructure, diagnosis

Four separate root causes behind one cache failure

The problem

Live availability changes were not showing up on the site. Some pages were up to a full day out of date. Everyone assumed it was one bug.

The diagnosis

First we had to establish whether the problem was the file or the cache, which meant testing the origin directly with a cache buster. That confirmed the origin was correct and the cache was serving stale content. The deployed purge turned out to be a targeted URL list rather than a full purge, and there were four independent gaps in it: URLs simply missing from the list, a meta deletion path with no hook attached, a second URL form for location terms that the purge never accounted for, and the subtle one, curated pages that query content rather than being taxonomy archives, so no term based loop could ever reach them. A fifth finding came out of the same read. An earlier implementation had been calling purge everything on every content change, which also flushed the one year image cache, so the AVIF files were perpetually cold. Seven of eight profiles sampled were returning MISS. Nobody had connected slow images to the purge logic, because they looked like two different problems.

The fix

All four fixed rather than one. That last cause is the kind of thing that survives three rounds of debugging, because the code looks correct and the loop it runs in simply never covers those pages. We then rewrote the purge itself as a targeted, HTML only invalidation that never touches images: rate limited to one purge per 60 seconds, chunked at 30 URLs per API call, and run non-blocking on shutdown so an editor pressing publish never waits on a CDN. Triggers were wired to every way state actually changes, including meta deletion, status transitions and comment events, and location terms are purged in both URL forms because one is canonical at the root while the other 301s to it. Image operations auto-purge too: optimisation plugins that write metadata directly are hooked through their own action, attachment IDs are resolved to every generated size, and purging a source jpg also evicts the AVIF derived from it.

The result

Six pages that had been stale for 14 to 24 hours matched the origin immediately after deployment, verified page by page rather than assumed, with edge ages of 43 to 47 seconds. The image cache stopped being flushed on every edit, so profile images now serve as AVIF with a cache HIT and stay warm for around 19 hours and beyond.

03
SEO architecture, content

A DR 72 domain ranking for nothing on a page it should have owned

The problem

A strong domain was ranking for zero keywords on a target page. The assumption, as it almost always is, was that the page needed more links.

The diagnosis

Before agreeing to a link campaign we checked who was actually ranking. The page one competitors were sitting at DR 16 to 32, well below the client. That proved authority was not the constraint, so link building would have been expensive and useless. The real causes were on the page: a canonical pointing at a redirect, two pages competing for the same intent, machine spun copy, and a 25 link block spreading equity across everything indiscriminately.

The fix

Rebuilt as a hub with spokes, splitting commercial and informational intent apart so the pages stopped competing. Corrected the canonical, replaced the spun copy with writing a person would finish reading, and cut the link block to five chosen internal links.

The result

The structural causes were removed and the page became eligible to rank on its merits. We also left behind a linking governance rule with a live ledger, so the tidy structure does not decay back into a link dump once we are gone.

04
Structured data

A schema graph quietly fighting itself

The problem

Search Console was reporting an entity issue and the structured data was a mess of overlapping claims made by different plugins over several years.

The diagnosis

There was a duplicate organisation entity, per item LocalBusiness markup that should never have been there, self serving review ratings, and invalid FAQPage markup, all live at the same time. Each individually looked defensible. Together they described a business that did not make sense.

The fix

Removed the duplicate organisation entity, disabled the per item LocalBusiness markup and the review ratings, promoted the remaining node to a single correct type, and stripped the invalid FAQPage markup. We deliberately kept the breadcrumbs and the #organization @id after researching the collision risk rather than removing them out of caution.

The result

One valid entity, validated through Google Rich Results, and the Search Console issue closed.

05
Product, bespoke tooling

Two customer facing tools built from scratch

The problem

The site needed two features that no plugin covered properly, and both had to stay fully crawlable because they were targeting real search demand.

The diagnosis

The first was a location search targeting a term with 33k searches a month. The obvious implementation, a JavaScript widget that fetches results on the client, would have been invisible to crawlers and worthless for the actual goal.

The fix

We built a geolocation search using the Geolocation API, Haversine distance sorting, radius filtering and reverse geocoded location labels, server rendered so it stays crawlable. Its geocoding layer maintains itself: a static map first, then a term meta cache, then a one off Nominatim lookup, which means new locations work with no code change at all. The second tool was a three way comparison built on real relationship data derived from post meta and made bidirectional, with SVG connector graphics, location aware combined pricing, localStorage persistence and undo and redo. DOM safe rendering throughout.

The result

Both are live, both are crawlable, and the location tool has needed no developer involvement to add locations since it shipped.

Engagements

Who this work was for.

Flagship, DR 88

High traffic lifestyle directory

We owned the whole technical side. Custom Sage theme, two bespoke customer facing tools, the full caching architecture, structured data, edge security, SEO strategy and copy. Around 151 hours logged and documented. Named on request.

Roughly 9,676 images were rebuilt into a custom three size plus AVIF pipeline, served with a one year max-age and returning cache HIT.

What that produces, as field data in CrUX on throttled mobile: gallery template LCP 372ms with INP 51ms, homepage LCP 1032ms with INP 78ms, and CLS 0.00 across the home, gallery and profile templates. The profile template measures a lab LCP of 1528ms with CLS also at 0.00. Lighthouse SEO is 100 out of 100, listed last because it is the least interesting number of the set.

Retained

Lamplit London

Theme development, sponsored link compliance using rel="sponsored", and deep link architecture.

Build

London Guide UK

Full site build, plus plugin stack selection, configuration and hardening.

Ongoing

SEO and competitor research

Continuous competitor, keyword, backlink and SERP analysis, feeding a prioritised roadmap rather than a report that sits unread.

Book me

Got something that looks like one of these?

Send the URL and the symptom. If it is a problem we have seen before we will tell you straight away, and if it is not, we will tell you that too.

Reply within one working day No obligation Your details stay with us

Takes about 60 seconds. No newsletter and no CRM sequence. Your details are used to reply to this enquiry and nothing else.