# Server-Side Caching on DomainIndia: Redis, Memcached, Varnish, and OPcache
TL;DR
Caching turns a 500ms database query into a 1ms memory lookup. This guide covers the four server-side caching layers you should understand — OPcache (PHP bytecode), Memcached/Redis (data cache), Varnish (HTTP response cache) — and when to use each on DomainIndia hosting.
## The four caching layers
Your web stack has four places to cache, from fastest to slowest:
| Layer | Caches | Read time | Where |
| OPcache | PHP bytecode | <0.01 ms | Built into PHP, on every plan |
| APCu | PHP user data (in-process) | <0.1 ms | PHP extension, usually enabled |
| Redis / Memcached | Any data (across processes) | 0.5–1 ms | Separate process, shared |
| Varnish / Cloudflare | Full HTTP responses | 5–20 ms (cache hit) | In front of your app |
Use all of them together for a well-tuned stack.
## Layer 1 — OPcache (PHP)
PHP compiles every file to bytecode on every request. OPcache stores the compiled version in memory so PHP skips parsing.
**Impact:** 2–3× speedup on PHP apps. Non-negotiable on production.
On DomainIndia cPanel/DirectAdmin, OPcache is **enabled by default** on PHP 7.4+. Verify via `php -i | grep opcache.enable` → `Opcache.enable => On`.
Tuning (in cPanel → MultiPHP INI Editor, or `.user.ini`):
```ini
opcache.enable=1
opcache.memory_consumption=256 ; MB — more = more files cached
opcache.max_accelerated_files=20000 ; number of PHP files
opcache.validate_timestamps=1 ; check file changes (set 0 in production + release restart)
opcache.revalidate_freq=2 ; seconds between checks
opcache.jit=1255 ; PHP 8+ JIT (tracing mode)
opcache.jit_buffer_size=64M
```
For Laravel/Symfony deployments: run `php artisan opcache:clear` (or similar) in deploy hook — otherwise OPcache serves old bytecode.
See our [PHP OPcache Configuration article](https://domainindia.com/support/kb/php-opcache-guide) for deep details.
## Layer 2 — APCu
In-memory key-value cache local to each PHP process. Good for small hot data — feature flags, config arrays, rate-limit counters.
```php
apcu_store('flag_new_checkout', true, 300); // 300s TTL
if (apcu_fetch('flag_new_checkout')) { /* new checkout */ }
```
Limits:
- Not shared across servers / across PHP-FPM pools cleanly
- Cleared on PHP-FPM reload
- Memory bound per-process
For shared-across-server caching, use Redis/Memcached instead.
## Layer 3 — Redis or Memcached
External in-memory store. Multi-process, multi-server, persistent (Redis).
**On DomainIndia hosting:**
| Plan | Redis available? | Memcached available? |
| Shared cPanel | Yes (local socket, shared instance) | Yes |
| Shared DirectAdmin | Ask support | Yes |
| VPS | Install yourself (1 command) | Install yourself |
| App Platform | Add Redis as a service | — |
### Redis — use cases
- Session storage (Laravel/Rails/PHP sessions)
- Queue backend (Laravel Queues, Sidekiq, BullMQ)
- Rate limiting (atomic INCR with expiry)
- Full-page cache
- Real-time features (pub/sub)
- Leaderboards (sorted sets)
Redis is the modern default — richer data types, persistence, pub/sub. Memcached is strict key-value only but slightly faster for pure lookups.
### Redis example — PHP
```php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$cached = $redis->get('user:42:profile');
if (!$cached) {
$profile = expensiveQuery();
$redis->setex('user:42:profile', 300, json_encode($profile));
return $profile;
}
return json_decode($cached, true);
```
### Redis example — Node.js
```javascript
import { createClient } from 'redis';
const redis = createClient();
await redis.connect();
const cached = await redis.get(`user:${id}:profile`);
if (cached) return JSON.parse(cached);
const profile = await db.user.findUnique({ where: { id } });
await redis.setEx(`user:${id}:profile`, 300, JSON.stringify(profile));
return profile;
```
### Install Redis on VPS
```bash
# AlmaLinux / Rocky
sudo dnf install -y redis
sudo systemctl enable --now redis
redis-cli ping # expect PONG
# Enable persistence (AOF)
sudo sed -i 's/^appendonly no/appendonly yes/' /etc/redis/redis.conf
sudo systemctl restart redis
```
## Layer 4 — Varnish / HTTP cache
Varnish sits in front of your app, caches full HTTP responses based on `Cache-Control` headers. Far less common in 2026 — Cloudflare/Fastly cover this with less operational burden.
**On shared hosting:** Varnish isn't available. Use [Cloudflare's edge cache](https://domainindia.com/support/kb/category/dev-cloudflare) instead — same result, zero config.
**On VPS:** Varnish is fine if you have specific needs (custom VCL rules, no Cloudflare dependency). Setup:
```bash
sudo dnf install -y varnish
# Edit /etc/varnish/default.vcl — proxy to your app on port 8080
sudo systemctl enable --now varnish
```
For most users: skip Varnish. Let Cloudflare handle HTTP-layer caching. Focus on Redis/OPcache.
## Cache invalidation strategies
"There are only two hard things in Computer Science: cache invalidation and naming things."
Three patterns:
**1. TTL-only (easy, eventually stale)**
- Set a short TTL (30–300s)
- Accept stale reads for that window
**2. Explicit invalidation (correct, more code)**
- When data changes, delete cache key
- Example: on `updateUser(42)`, `redis.del('user:42:profile')`
**3. Tags (elegant, complex)**
- Tag cached entries: `user:42:profile` tagged with `user:42`
- On change, invalidate all entries with tag `user:42`
- Laravel Cache supports this natively (`Cache::tags(['users'])->put(...)`)
For most apps: TTL-only for read-heavy data (feeds, product catalogs), explicit invalidation for user-specific (profile, cart).
## Measuring cache effectiveness
Without measurement, you're guessing.
**Redis:** `redis-cli INFO stats` → `keyspace_hits` vs `keyspace_misses`. Ratio tells you hit rate.
**Cloudflare:** Dashboard → Analytics → Cache. Look for CF-Cache-Status: HIT ratio.
**App-level:** log cache HIT/MISS to your logger. Aggregate in Grafana.
Good targets:
- Redis hit rate > 80%
- Cloudflare HTML cache hit > 50% (for cacheable pages)
- OPcache hit rate > 99%
## Common pitfalls
## FAQ
Q
Redis or Memcached — which?
Redis, almost always. Richer data types, persistence, pub/sub. Memcached only if you have a specific reason (pure-simplicity key-value, legacy systems).
Q
Can I use Redis on shared hosting?
On our cPanel shared plans, yes — a shared Redis instance is available via Unix socket. Check with support for connection string. For DirectAdmin, confirm with our support team.
Q
Do I need Varnish if I'm on Cloudflare?
No. Cloudflare's edge cache does everything Varnish does + free DDoS + global CDN. Varnish is only for special cases (custom VCL rules, on-prem requirements).
Q
How do I cache database query results in Laravel?
Cache::remember('users.active', 300, fn() => User::where('active', true)->get()). Laravel picks Redis automatically if configured.
Q
Cache everything vs cache nothing — where to start?
Measure slowest endpoints first (application logs or APM). Cache the top 3 slowest reads. Iterate. Premature caching adds complexity without measurable gain.
Need Redis / Memcached at scale? VPS with root access gives you full control.
View VPS plans