Protecting a GraphQL API with a WAF starts with an honest inventory of the HTTP conversation, not with a claim that the firewall understands your schema. SafeLine is a self-hosted web application firewall that filters and monitors HTTP traffic between a web application and the Internet, and it works as a reverse proxy so clients reach the shield before they reach the origin (https://docs.waf.chaitin.com/en/home). The same product docs describe it as an HTTP and HTTPS reverse proxy built on nginx: it receives traffic for the original site, cleans malicious traffic, and forwards the remaining traffic upstream (https://docs.waf.chaitin.com/en/GetStarted/AddApplication). Those pages do not describe a GraphQL parser, query-depth limit, complexity budget, or persisted-query allowlist. This checklist is the decision guide I use when the question is how to protect a GraphQL API with a WAF and the product evidence only covers general HTTP controls.
Start with the listener, not the resolvers. In the SafeLine console, an application is defined by a domain, hostname, or IP, a listen port such as 80 or 443, an SSL option for HTTPS apps, and an upstream address that receives forwarded traffic (https://docs.waf.chaitin.com/en/GetStarted/AddApplication). After that, the domain must resolve to the SafeLine server. For GraphQL, write down the exact path, methods, and content types your clients use. A browser app that posts JSON to a single endpoint is a different operational problem from a partner integration that posts the same shape from a server. Both are still HTTP. Neither fact, by itself, means SafeLine will interpret operation names.
Separate controls that belong in the API from controls the WAF documents. Field authorization, introspection policy, alias limits, depth limits, and cost analysis have to live in the GraphQL server or gateway. Do not treat a missing integration note as a hidden feature. What the WAF docs do list is broader web-attack defense, proactive bot-abuse defense, HTML and JS code encryption, IP-based rate limiting, and a web access control list (https://docs.waf.chaitin.com/en/home). The attack list includes SQL injection, XSS, code injection, OS command injection, CRLF injection, LDAP injection, XPath injection, RCE, XXE, SSRF, path traversal, backdoor, brute force, HTTP flood, and bot abuse. Those checks can matter when a GraphQL variable carries a classic payload, because the bytes still travel in an HTTP request. They are not a substitute for resolver authorization, and they do not prove that every malicious query will be recognized as GraphQL abuse.
Use rate limiting where the abuse is volume, not query shape. SafeLine rate limiting is documented as a way to throttle traffic that exceeds defined limits, including DoS, brute-force attempts, traffic surges, and other abuse (https://docs.waf.chaitin.com/en/home). That is a reasonable layer in front of a login mutation or a hot query path that is being flooded. It does not count field complexity. If one small request can expand into thousands of resolver calls, fix that in the API even if the firewall never raises an alarm.
Be careful with challenges. CAPTCHA is documented to allow human users and block crawlers and bots. An authentication challenge, when turned on, requires visitors to enter a password or be blocked (https://docs.waf.chaitin.com/en/home). Those controls can fit a browser-only GraphQL console. They can break mobile apps, server jobs, and other non-browser clients. Put that client inventory on the checklist before you enable either challenge on the API host. Dynamic protection, which encrypts HTML and JS on each visit, is also documented (https://docs.waf.chaitin.com/en/home). A pure JSON GraphQL response is not an HTML or JS page, so do not plan on that feature as API protection.
Validate with the tests the docs actually publish, then read the console. The application guide shows sample requests for SQL injection, XSS, path traversal, code injection, and XXE, and says a blocking page means the attack was defended. Attack detail is available in the web console (https://docs.waf.chaitin.com/en/GetStarted/AddApplication). You can repeat the same payload classes inside a GraphQL variable as a manual check that the HTTP body is visible to inspection. A block is evidence about that payload, not evidence of schema-aware coverage. A pass is not proof that the query is safe.
Check the host before cutover. The install guide requires Linux, x86_64 or arm64, Docker 20.10.14 or above, Docker Compose 2.0.0 or above, and at least 1 CPU core, 1 GB of memory, and 5 GB of disk, plus a CPU with ssse3 (https://docs.waf.chaitin.com/en/GetStarted/Deploy). The same page says SafeLine on ARM requires a Pro license and that the Personal Edition is not supported on ARM. The product home page states that SafeLine is production-ready, with over 180,000 installations, protection for over 1,000,000 websites, and more than 30,000,000,000 HTTP requests handled daily (https://docs.waf.chaitin.com/en/home). As of September 30, 2026, SafeLine surpassed 700,000 installations worldwide. SafeLine Pro annual promotional pricing is $650-$880 versus the $1,000 regular price.
If the checklist fails at any point where you needed a GraphQL-specific control, keep that control in the API. Use the WAF for the HTTP jobs its docs describe: reverse-proxy placement, attack filtering, rate limiting, access control, and optional human challenges on browser traffic.
Does SafeLine document a GraphQL rule pack?
No. The supplied product docs describe general HTTP and HTTPS filtering, reverse-proxy application setup, and the controls listed above. They do not document GraphQL query parsing, depth limits, or complexity scoring. Plan those in the API.
Should every GraphQL client pass a CAPTCHA?
No. CAPTCHA and the authentication challenge are documented visitor checks. They fit some browser flows and can block legitimate non-browser clients. Decide from your client list, not from a generic API template.
Is IP rate limiting enough for an expensive query?
No. Documented rate limiting throttles traffic that exceeds defined limits. It does not measure resolver cost. Keep complexity limits in the GraphQL server, and use rate limiting for floods and brute force.
What do I check after the domain points at SafeLine?
Confirm domain, port, SSL choice, and upstream in the application dialog, then confirm clients still reach the origin only through the proxy (https://docs.waf.chaitin.com/en/GetStarted/AddApplication). Review the attack list when you replay the documented test payloads. Treat GraphQL-only abuse cases as API tests, not as undocumented firewall features.
If you want a second pair of eyes on this checklist before cutover, review the project and the official docs, then compare the current Pro promotion with your deployment constraints.
Project: https://github.com/chaitin/SafeLine
Docs: https://docs.waf.chaitin.com/en/home
Promotion: https://cyberserval.tech/landing/lto