· 6 min read

Live vs Static Mode: Which One Should You Use?

LangSyncer supports two modes for delivering translations to your Laravel app: static (files on disk) and live (cache plus webhooks). Both serve the exact same published translations from the same CDN — the only difference is how and when your application picks up updates. Understanding that difference helps you pick the right one, and switching later is a one-line change.

The Problem in a Real Laravel App

Here's a support question we see often: "I published a translation change in the dashboard, but production still shows the old text."

Nine times out of ten, the app is running the default configuration:

CLI_TRANSLATOR_API_KEY=lh_proj_...
CLI_TRANSLATOR_CDN_URL=https://cdn.langsyncer.com
# CLI_TRANSLATOR_CLIENT_MODE not set — defaults to static

In static mode, your app reads translations from local files and only updates them when something triggers a sync:

php artisan translator:sync

If that command isn't in your deploy script and you never wired up a webhook, your app happily serves whatever it downloaded last week. Nothing is broken — the mode just doesn't match your expectations. So let's look at what each mode actually does under the hood.

The Two Modes, Side by Side

The .env diff tells most of the story:

# Static mode: translations live on disk
CLI_TRANSLATOR_CLIENT_MODE=static
CLI_TRANSLATOR_SYNC_STRATEGY=overwrite          # or "merge"
CLI_TRANSLATOR_METADATA_PATH=storage/translator-client
# Live mode: translations live in your Laravel cache
CLI_TRANSLATOR_CLIENT_MODE=live
CLI_TRANSLATOR_CLIENT_WEBHOOK_ENABLED=true
CLI_TRANSLATOR_CLIENT_CACHE_DRIVER=redis        # defaults to your app's cache driver
CLI_TRANSLATOR_CLIENT_CACHE_PREFIX=translator
CLI_TRANSLATOR_CLIENT_CACHE_TTL=3600

Static Mode: Files on Disk

translator:sync downloads your published translations from the CDN into storage/translator-client/, and your app reads from those local files at runtime. Updates happen when you re-run the sync — manually, in a deploy script, or triggered by a webhook.

The CLI_TRANSLATOR_SYNC_STRATEGY variable controls what sync does to existing files. overwrite replaces local files completely with the CDN version. merge keeps local-only keys and lets CDN values win on conflicts — useful if some translations still live only in your repo.

Best for: shared hosting and VPS setups, teams that want translation updates coupled to deployments, and maximum runtime reliability — once files are synced, there's no external dependency when serving requests.

Live Mode: Cache Plus Webhooks

In live mode, translations are stored in your Laravel cache (Redis, database, whatever you've configured). When you publish in the dashboard, LangSyncer sends a webhook to your app, the cache invalidates, and the next request fetches fresh translations from the CDN.

The caching knobs matter here. CLI_TRANSLATOR_CLIENT_CACHE_TTL (default 3600 seconds) is your safety net: even if a webhook never arrives, cached translations expire after an hour and get refetched. CLI_TRANSLATOR_CLIENT_CACHE_PREFIX keeps translation keys namespaced so they don't collide with the rest of your cache. And the driver needs to be persistent and shared — Redis or database. The file driver is a trap on serverless, where each Lambda instance has its own ephemeral filesystem and would hold its own stale copy.

Best for: serverless (Laravel Vapor, AWS Lambda), teams that want publishes visible without touching the server, and content teams managing their own translations.

Switching an App to Live Mode

  1. Change the mode. Update .env:
CLI_TRANSLATOR_CLIENT_MODE=live
CLI_TRANSLATOR_CLIENT_WEBHOOK_ENABLED=true
  1. Create the webhook. In the LangSyncer dashboard, open your project's Actions modal, go to the Webhooks tab, and add a webhook pointing at your app's endpoint — the package registers /api/translator/webhook by default (configurable via CLI_TRANSLATOR_CLIENT_WEBHOOK_ROUTE). The URL must be HTTPS. Subscribe to the Translations Published event — this one is required for live mode to work. Each webhook gets a secret key, and the translator-client package verifies signatures automatically. Full details are in the projects documentation.

  2. Warm up the cache. Don't make your first visitor pay the cost of a cold fetch:

php artisan translator:warmup

Add this to your deploy script so every release starts with a pre-populated cache.

  1. Verify. Check that everything is wired up:
php artisan translator:status
  1. Test the loop. Edit a translation in the dashboard, publish, and reload your app. CDN files regenerate about 30 seconds after publishing, and webhooks dispatch within 2-3 minutes — so give it a moment before assuming something's wrong.

For a deeper look at the webhook flow, see Real-Time Translation Updates with Webhooks.

Or Let LangSyncer Decide: Auto Mode

CLI_TRANSLATOR_CLIENT_MODE=auto

Auto mode detects your environment: serverless platforms like Vapor get live mode, traditional hosting gets static. It's a sensible default if you deploy the same codebase to different environments.

When Each Mode Wins — and When It Doesn't

Skip live mode when:

  • You don't have a persistent, shared cache driver in production. Live mode on the file driver across multiple servers means inconsistent translations between them.
  • Your app can't accept inbound webhooks (behind a firewall, no public HTTPS endpoint). You'd be relying on the cache TTL alone, so updates lag up to an hour.
  • You want translation changes to go through the same release gate as code. Static mode with sync-on-deploy gives you exactly that.

Skip static mode when:

  • You're on serverless, where there's no durable local disk to sync files onto.
  • Non-technical teammates publish translations and expect to see them live without asking a developer to run anything.

Neither mode changes what your Blade templates look like — __('messages.welcome') works identically in both. And if you're comparing this whole setup against plain lang files in git, the LangSyncer vs Laravel lang files comparison covers that decision separately.

Gotchas

  • The default mode is static. If you expected instant updates but never set CLI_TRANSLATOR_CLIENT_MODE=live, that's the whole mystery.
  • Live mode needs the "Translations Published" webhook event. Without it, your cache only refreshes when the TTL (default 3600 seconds) expires — updates will feel randomly delayed.
  • "Instant" means seconds to a couple of minutes, not milliseconds. CDN regeneration is delayed roughly 30 seconds after publish, and webhook dispatch takes 2-3 minutes. Don't panic-debug during that window.

My Recommendation

Start with live mode. The instant updates are worth it, and you can always switch to static if you need deployment-coupled control — it's one environment variable either way.

For high-traffic production apps: live mode with Redis, translator:warmup on every deploy, and the default TTL as your fallback. Both modes read the same published data, so there's no migration cost to changing your mind.

Related Posts


Try both modes →

We use cookies to improve your experience and analyze site traffic. Cookie Policy

Cookie Preferences

Essential

Required for the site to work

Analytics

Help us improve the site

Marketing

Personalized ads and content