Skip to main content

Why You Shouldn’t Cache

Menu data is more dynamic than it appears. A dish can sell out mid-service. A location can 86 an ingredient. Nutrition data gets corrected. Seasonal specials appear and disappear. When a guest with a peanut allergy sees stale data that doesn’t reflect a recipe change, that’s not just a bad experience—it’s a safety issue. EveryBite handles all caching internally. We’ve invested heavily in a multi-layer caching infrastructure that ensures:
  • Fast response times optimized for real-time menu browsing
  • Real-time accuracy for availability and nutrition data
  • Automatic invalidation when upstream data changes
Your job is simple: call the API, trust the response, display it to the guest.

Our Caching Architecture

EveryBite is built on AWS using industry best practices for performance, reliability, and security. Our infrastructure spans multiple availability zones with automatic failover, and we leverage AWS’s global network to minimize latency for your users regardless of location. We handle caching at multiple layers so you don’t have to:
LayerWhat It Does
CloudFrontGlobal CDN for DDoS protection and TLS termination
ElastiCache (Redis)Application-level caching of menu and nutrition data
DatabaseSource of truth, updated by Olo/Toast/Admin
When menu data changes upstream (Olo webhook, admin update), we invalidate affected caches immediately. You always get fresh data without managing cache invalidation yourself.

How We Sync Data

EveryBite integrates with various third-party systems to keep menu, nutrition, and allergen data current. Data flows into our platform through three sync methods, each with different freshness characteristics.

Sync Methods

Real-time Changes sync instantly via webhooks. When the source system updates data, we’re notified immediately and propagate the change. No action required—updates flow automatically. This provides the best data freshness for systems that support real-time notifications. Scheduled Data syncs automatically every hour. We connect to third-party APIs and pull updates on a regular schedule. No action required—freshness is within 1 hour of source changes. File Upload Data updates when new files are provided. Supports PDFs, spreadsheets, and structured exports from third-party systems. Freshness depends on when files are uploaded.

Connectors

Each third-party system has a dedicated connector—a translation layer that maps between EveryBite’s internal data model and the external system’s format and API. Connectors handle the specifics of how each integration works while using one of the sync methods above.
SystemSync MethodFreshness
MenuCalcReal-timeInstant
TrustwellScheduled or File UploadUp to 1 hour or on upload
PDF MenusFile UploadOn upload
For real-time connectors like MenuCalc, changes to recipes, nutrition, allergens, or ingredients are reflected in the API within seconds. For scheduled connectors, changes appear within 1 hour.

What This Means for You

Don’t Cache API Responses

// ❌ Don't do this
const cachedMenu = localStorage.getItem('menu');
if (cachedMenu && !isExpired(cachedMenu)) {
  return JSON.parse(cachedMenu);
}
const menu = await fetchMenu();
localStorage.setItem('menu', JSON.stringify(menu));

// ✅ Do this instead
const menu = await fetchMenu();

Don’t Add Cache Headers

// ❌ Don't do this
fetch(url, {
  headers: {
    'Cache-Control': 'max-age=300'
  }
});

// ✅ Just call the API
fetch(url);

Don’t Batch Requests to Reduce Calls

// ❌ Don't do this
const allDishes = await fetchAllDishes();
const dish = allDishes.find(d => d.id === dishId);

// ✅ Fetch what you need when you need it
const dish = await fetchDish(dishId);

When Fresh Data Matters Most

Allergen Information

A recipe change that adds a new allergen must be reflected immediately. Our system propagates allergen updates within seconds of an admin change.
1

Recipe Updated

Admin updates a recipe in the portal, adding dairy as an ingredient.
2

Cache Invalidated

EveryBite immediately invalidates all cached data for that dish.
3

Fresh Data Served

Next API request for that dish returns updated allergen information showing dairy.
4

Warning Displayed

Your app shows the dairy allergen warning to guests with dairy restrictions.

Real-Time Availability

When a dish sells out, the update propagates through webhooks:
  1. POS marks dish unavailable
  2. Olo/Toast sends webhook to EveryBite
  3. We invalidate caches and update availability
  4. Next API call reflects the change
Availability changes typically propagate within 5 seconds of the POS update.

Nutrition Corrections

When nutrition data is corrected (calorie count was wrong, serving size updated), caches are invalidated immediately. Guests making health-conscious decisions always see accurate information.

Performance Without Client Caching

You might worry that not caching will hurt performance. It won’t. Here’s why:
ConcernOur Solution
LatencyEdge caching at 200+ global locations
Repeated requestsApplication-level caching with smart invalidation
High trafficAuto-scaling infrastructure handles spikes
BandwidthEfficient GraphQL—request only fields you need

The One Exception: Filter Options

The filterOptions query returns available diets, allergens, and nutrient ranges for a chain. This data changes rarely (when a chain adds/removes menu items). You may cache this response briefly:
// Filter options can be cached for a few minutes
const FILTER_OPTIONS_TTL = 5 * 60 * 1000; // 5 minutes

async function getFilterOptions() {
  const cached = filterOptionsCache.get(chainId);
  if (cached && Date.now() - cached.timestamp < FILTER_OPTIONS_TTL) {
    return cached.data;
  }

  const data = await fetchFilterOptions();
  filterOptionsCache.set(chainId, { data, timestamp: Date.now() });
  return data;
}
Only cache filterOptions. Never cache search results, dish details, or any data that includes nutrition, allergens, or availability.

Best Practices

Trust the API

Our caching is optimized for your use case. Let us handle freshness.

Fetch on Demand

Request data when you need it. Don’t prefetch and store.

Use GraphQL Efficiently

Request only the fields you need—less data transferred, faster responses.

Handle Errors Gracefully

If a request fails, retry rather than falling back to stale cached data.

Summary

Data TypeCache Locally?Why
Search resultsNoMatch status depends on real-time availability
Dish detailsNoNutrition and allergens must be current
AvailabilityNoChanges in real-time
Filter options5 min maxChanges rarely, safe to cache briefly
Let us handle the complexity of caching. You focus on building a great guest experience.