Types that mean something
Money as a decimal, not a float or a string. Dates as dates. Booleans as booleans. Storing everything as text pushes validation into every query that reads it.
Sites that load fast and convert
Custom builds and integrations
Bounded, auditable, human-approved
Being found, staying fast, staying safe
Software & Applications · Service 14
Caching hides a slow database until it cannot. Schema design and query performance decide whether a system stays quick as data grows — and almost every site that "got slower over time" got slower here, not in the front end.
The pattern is consistent. A site launches fast because there are two hundred rows in every table. Two years later there are two hundred thousand, a report page takes eleven seconds, and everyone blames the hosting. Better hosting buys a little time and considerable expense. Fixing the query usually costs less and lasts longer.
Query lab
A worked example: an orders report on a table of roughly 240,000 rows. Toggle the changes and watch the plan and the timing respond.
These are the four adjustments that resolve the majority of real-world slowness, in roughly the order of impact. None of them involve buying a bigger server. The point of showing the plan alongside the timing is that the plan is the evidence — a query that got faster for a reason you cannot name will get slow again for a reason you cannot name either.
Query
Execution plan
The classic
The single most common performance bug in web applications has a name: N+1. One query fetches a list, then the code runs another query for every item in it — invisibly, inside a loop, usually inside a template.
It is easy to miss because each individual query is fast. Nothing looks wrong in the code, and it performs perfectly in development where the list has five rows. In production with fifty, the page makes fifty-one round trips to the database and takes a second and a half to render. Drag the slider and watch both sides.
Naive — a query per row
Eager loaded — two queries
Foundations
Query tuning fixes symptoms. Schema design decides how many symptoms you will have. These are the choices that are inexpensive at the start and expensive in year three.
A schema is not just where data lives — it is a set of guarantees about what states your data can be in. A well-designed one makes certain bugs structurally impossible: an order cannot reference a customer who does not exist, a price cannot be text, two rows cannot claim the same booking slot. Every guarantee the database does not enforce becomes something the application has to remember to check, in every place, forever.
Money as a decimal, not a float or a string. Dates as dates. Booleans as booleans. Storing everything as text pushes validation into every query that reads it.
Relationships declared and enforced by the database, so orphaned records cannot exist. Cleaning up orphans years later is archaeology.
An index per query you actually run, not one per column. Every index speeds reads and slows writes, so each needs a reason.
Then denormalised carefully where measurement justifies it. Duplicating data before you have a performance problem creates a consistency problem instead.
NULL should mean "unknown", never "zero" or "false" or "not applicable". Conflating them produces reports that quietly disagree with each other.
Identifier sizes, character sets and timezone handling chosen for where the business is going, because changing them on a large live table is an outage.
Deciding early what "deleted" means. Retro-fitting it means auditing every query to add a condition somebody will eventually forget.
Every schema change scripted, versioned and repeatable, so staging and production cannot drift apart unnoticed.
An untested backup is a hope. Part of the work is proving a restore actually produces a working system.
Questions
Often, but not always — and guessing is expensive. The audit starts by measuring: slow query logs, the actual execution plans of the pages people complain about, and where time is really spent. Sometimes the answer is images and the database is fine.
What is nearly always true is that if the site got slower gradually as data grew, rather than after a specific change, the database is the first place to look.
Temporarily, and at permanent cost. Doubling the hardware might halve the time of a query doing unnecessary work, but the underlying inefficiency remains and returns as data grows. An index that turns a full scan into a lookup is often a thousand-fold improvement, not a doubling.
Sometimes more hardware genuinely is the right answer. We will tell you when that is the case rather than selling optimisation you do not need.
Frequently, yes. Indexes and configuration changes are invisible to the application and often deliver most of the improvement. Query rewrites and schema changes need code changes, and N+1 problems are code problems by definition.
We sequence it so the no-code-change wins land first — you feel the difference before committing to anything larger.
It can be, which is why nothing is applied directly. Changes are tested against a copy with production-scale data, because an index that takes two seconds on a test table can lock a large one for minutes. Adding indexes is generally safe and reversible; altering columns on big tables needs an online approach and a planned window.
We work with MySQL and MariaDB, which is what most WordPress and WooCommerce sites run, and PostgreSQL for custom applications where its stricter typing and richer features earn their keep.
For an existing system, the honest answer is usually to make what you have work well rather than to migrate. Changing engine is a real project, and it rarely fixes a problem that better queries would not.
A fixed-price review with a written report: schema assessment, index coverage against the queries you actually run, the slowest operations with their plans, configuration review, backup verification, and a prioritised list of changes ranked by impact against effort.
You get the report regardless of whether we do the work. Several clients have handed it to their own developers, which is a perfectly good outcome.
Common, not inevitable. WordPress stores most data in a key-value meta table, which is flexible and gets expensive at scale — product filtering and reporting are usually the first things to suffer.
There are established ways to address it: targeted indexes, lookup tables for the attributes you filter on, and moving heavy reporting off the live query path. This is one of the more frequent reasons people call.
Often paired with
Call back
Leave a number and a good time. We will call you back to talk about what you are trying to build — no charge for the conversation.
Or call us directly +1 (647) 385-5532