This complete guide covers all 9 Web Platform tutorials on TheCodeForge, organised by topic.
WordPress and GraphQL sit at opposite ends of web engineering and share one property that shapes every error in this track: both hide the database behind a layer that makes expensive things look cheap. In WordPress it is a plugin architecture where any of forty plugins can hook a query onto every page load. In GraphQL it is a resolver graph where a client asking for one extra nested field can multiply your query count by the size of a list.
So the debugging skill is the same on both sides: make the invisible work visible. A white screen is not a mystery once errors are being logged. An N+1 explosion is not a mystery once you count queries per request. Most of the fixes below are about installing that visibility first and only then changing code.
A blank page means PHP hit a fatal error while output buffering was on and display of errors was off. The error exists; you just cannot see it. So the first move is never to start deactivating plugins by guesswork — it is to turn logging on and read the actual message, which usually names the file and line directly.
Once you can see it, the shape of the problem is almost always one of three: exhausted memory, a fatal in a plugin or theme after an update, or a PHP version incompatibility where a plugin uses syntax the installed PHP rejects.
| Symptom | Read this first | Usual cause |
|---|---|---|
| Blank white page | wp-content/debug.log, then the PHP-FPM error log | Fatal error in a plugin or theme, or exhausted memory |
| Error establishing a database connection | Credentials in wp-config.php, then whether MySQL is accepting connections at all | Wrong host or socket, MySQL down, or connection limit reached on shared hosting |
| Too many redirects | siteurl and home in wp_options | Site URL and the actual scheme or domain disagree, often after adding TLS behind a proxy |
| REST API 401 while logged in | Whether the nonce is being sent, and the Authorization header survives the server | Missing X-WP-Nonce, or Apache stripping Authorization before PHP sees it |
WordPress canonicalises requests: if the incoming URL does not match the stored siteurl, it redirects to the stored one. Put it behind a TLS-terminating proxy and the loop is immediate — siteurl says https, the proxy forwards plain HTTP, PHP sees a non-TLS request and redirects to HTTPS, the proxy forwards it again, forever.
The fix is to tell PHP what the proxy already knows, and to do it before WordPress boots.
X-Forwarded-Proto when the request genuinely cannot reach PHP except through your proxy. If the origin is directly reachable, a client can set that header itself, and you have handed it control over how your application understands its own scheme.A GraphQL resolver is called once per field per object. Ask for 50 posts and each post's author and the author resolver runs 50 times, each issuing its own query. The query is fast; there are simply 51 of them. Nothing in the schema hints at this, which is why N+1 is the defining performance problem of GraphQL APIs.
DataLoader fixes it by batching within a tick of the event loop: individual load(id) calls are collected, dispatched as one query, and the results distributed back to the callers. The critical detail is lifetime — a loader must be created per request, because its cache is a per-request cache. Sharing one across requests serves stale data across users.
DataLoader must return results in the same order as the requested keys, with a null or error placeholder for missing ones. Returning the database's natural order is the most common implementation bug, and it silently attaches the wrong author to the wrong post.
Cannot return null for non-nullable field is the schema enforcing a promise you made. Because GraphQL nullability propagates upward, a null in a non-null field nulls its parent, and if the parent is also non-null the error climbs until it finds something nullable — which is why one missing row can blank an entire response. The lesson is to be honest in the schema: mark a field non-null only when your resolver can always produce it.
Query depth is the mirror image. A schema where a post has an author who has posts is a cycle, and a client can nest it as deep as it likes, so a small query can demand an enormous amount of work. Depth limits, complexity scoring and a persisted-query allow-list are the three standard defences, and public APIs generally need at least two of them.
| Control | Stops | Cost |
|---|---|---|
| Depth limit | Deeply nested cyclic queries | Simple to add; blunt, and a wide shallow query still gets through |
| Complexity scoring | Expensive queries regardless of shape, by weighting fields and list sizes | Needs per-field weights and tuning, but is the control that matches actual cost |
| Persisted queries | Anything the client did not register in advance | Strongest control; only workable when you own every client |
| Pagination limits | Unbounded list arguments multiplying everything below them | Cheap, and should be a default on every list field |
WP_DEBUG_LOG first and read debug.log — the fatal error names the file, which names the plugin, with no deactivation needed. If the log is empty because the failure happens before logging initialises, check the PHP-FPM error log. Bisecting plugins should be the last resort, not the first move.X-WP-Nonce, WordPress treats the request as unauthenticated even with a valid session cookie. The other frequent cause is the server stripping the Authorization header before PHP sees it, which needs a rewrite rule to pass it through.Every tutorial starts with a plain-English analogy — then real code, then interview questions.
Browse Web Platform Tutorials →