Flask + Redis Counter¶
A page visit counter built with Flask and Redis. Every page load increments a counter stored in the managed Redis cache. This example demonstrates how AppMecca handles cache provisioning -- a single cache: enabled: true line injects Redis connection details into your containers.
Source: git@gitlab.com:appmecca-sample-apps/flask-redis-counter.git
What This App Demonstrates¶
- Managed Redis cache --
cache: enabled: trueauto-provisions Redis connection details - Stateless app with external state -- the Flask process holds no state; all state lives in Redis
- Injected environment variables --
REDIS_URLandCELERY_BROKER_URLare set automatically
appmecca.yaml¶
containers:
- name: web
dockerfile: Dockerfile
context: .
deploy:
- name: web
container: web
port: 5000
health_check:
path: /health
redis:
enabled: true
When cache: enabled: true, AppMecca injects these environment variables into every container:
| Variable | Example Value | Description |
|---|---|---|
REDIS_URL |
redis://<cache-host>:6379/0 |
Redis connection URL |
CELERY_BROKER_URL |
(same as REDIS_URL) |
Convenience alias for Celery |
CACHE_PREFIX |
<app>:<branch>: |
Key namespace for this app + branch |
REDIS_URL and CELERY_BROKER_URL contain the same URL. CELERY_BROKER_URL is provided because Celery looks for it by default, even if your app does not use Celery.
Shared cache, namespaced keys
The managed Redis cache is shared across all apps in the same environment. AppMecca injects CACHE_PREFIX (built from the app's canonical name and branch) so keys stay isolated between apps and between branches. Use this prefix in your application code to prevent key collisions — read it from the environment rather than hardcoding it, because the canonical app name includes your group.
Application Code¶
app.py¶
import os
from flask import Flask, jsonify
import redis
app = Flask(__name__)
# Connect to Redis using the APPMECCA-injected URL
r = redis.from_url(os.environ.get("REDIS_URL", "redis://localhost:6379/0"))
PREFIX = os.environ.get("CACHE_PREFIX", "")
@app.route("/")
def index():
count = r.incr(f"{PREFIX}visits")
return f"This page has been visited {count} times."
@app.route("/health")
def health():
return jsonify({"status": "healthy"})
The app reads REDIS_URL to connect to Redis and uses CACHE_PREFIX to namespace its keys. This means:
- Multiple apps sharing the same cache will not interfere with each other
- Branch deployments get their own prefix, so a
feature/dark-modedeploy cannot read or clobbermain's counters
Dockerfile¶
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
No entrypoint script is needed here -- there is no database to wait for and no migrations to run. Redis is immediately available when the container starts.
Deploy It¶
# Register the app
mecca register git@gitlab.com:appmecca-sample-apps/flask-redis-counter.git -e dev
# Build the Docker image
mecca build trigger -e dev -g git@gitlab.com:appmecca-sample-apps/flask-redis-counter.git
# Deploy
mecca app deploy -e dev flask-redis-counter
Your app is live at https://flask-redis-counter-web.dev.appmecca.net. The service name
(web) is always part of the hostname, even though this app has only one service — run
mecca app show flask-redis-counter -e dev to see the exact URL for your group.
Verify¶
# Visit the counter
curl https://flask-redis-counter-web.dev.appmecca.net/
# "This page has been visited 1 times."
curl https://flask-redis-counter-web.dev.appmecca.net/
# "This page has been visited 2 times."
# Health check
curl https://flask-redis-counter-web.dev.appmecca.net/health
# {"status": "healthy"}
Database + Cache Together¶
Many applications need both PostgreSQL and Redis. You can enable both:
When both are enabled, every container receives:
| Variable | Source |
|---|---|
DATABASE_URL |
Database (the canonical connection string — prefer this) |
DB_HOST, DB_PORT, DB_NAME, DB_USER, DB_PASSWORD |
Database (the same details, split out) |
REDIS_URL |
Cache |
CELERY_BROKER_URL |
Cache |
CACHE_PREFIX |
Cache |
See the Django Celery Tasks example for an app that uses both.
Key Takeaways¶
- Add
cache: enabled: trueto yourappmecca.yaml-- AppMecca injectsREDIS_URLautomatically - Use
CACHE_PREFIXto namespace your Redis keys and avoid collisions with other apps - No entrypoint script is needed for cache-only apps -- Redis is always available
- The cache is shared across all apps in an environment, which is exactly why the prefix matters
- Note this is the top-level
cache:block (the managed Redis cache). The per-servicedeploy[].cache:block is a different feature — it configures the AppMecca edge cache in front of a service
What's Next?¶
- Django Celery Tasks -- Use Redis as a Celery message broker with background workers
- Cache Configuration -- Full reference for cache settings
- Django + Vue Notes -- Database integration without cache