• Home
  • Cloud VPS
    • Hong Kong VPS
    • US VPS
  • Dedicated Servers
    • Hong Kong Servers
    • US Servers
    • Singapore Servers
    • Japan Servers
  • Company
    • Contact Us
    • Blog
logo logo
  • Home
  • Cloud VPS
    • Hong Kong VPS
    • US VPS
  • Dedicated Servers
    • Hong Kong Servers
    • US Servers
    • Singapore Servers
    • Japan Servers
  • Company
    • Contact Us
    • Blog
ENEN
  • 简体简体
  • 繁體繁體
Client Area

Celery Task Queue on Hong Kong VPS: Async Background Jobs (2026)

September 14, 2026

Celery is Python’s most widely used distributed task queue — it handles everything from sending emails in the background to processing uploaded images to running scheduled reports. On a Hong Kong VPS, Celery workers running alongside your Django or FastAPI application process background tasks efficiently, keeping API responses fast by offloading heavy work to dedicated worker processes rather than blocking the web server during long operations.


When to Use Celery

  • Send transactional emails without delaying API response
  • Process uploaded images (resize, watermark, convert to WebP)
  • Generate PDF reports or Excel exports
  • Call slow external APIs (WeChat, payment gateways) asynchronously
  • Scheduled maintenance tasks (cleanup, reports, data sync)
  • Retry failed operations with exponential backoff
  • Fan-out notifications (send to 10,000 users in parallel)

Step 1: Install Celery and Redis

<code">apt install -y redis-server
systemctl enable --now redis-server

source /opt/myapp/venv/bin/activate
pip install celery[redis] redis flower

Step 2: Configure Celery

<code"># myapp/celery.py — Celery application configuration
import os
from celery import Celery
from celery.schedules import crontab

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myapp.settings')

app = Celery('myapp')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

# Scheduled tasks (Celery Beat)
app.conf.beat_schedule = {
    'cleanup-old-sessions': {
        'task': 'myapp.tasks.cleanup_expired_sessions',
        'schedule': crontab(hour=2, minute=0),
        'options': {'timezone': 'Asia/Hong_Kong'},
    },
    'sync-inventory': {
        'task': 'myapp.tasks.sync_inventory',
        'schedule': crontab(minute='*/15'),
    },
    'weekly-sales-report': {
        'task': 'myapp.tasks.generate_weekly_report',
        'schedule': crontab(hour=9, minute=0, day_of_week=1),
        'options': {'timezone': 'Asia/Hong_Kong'},
    },
}

app.conf.update(
    broker_url=os.environ.get('REDIS_URL', 'redis://localhost:6379/0'),
    result_backend=os.environ.get('REDIS_URL', 'redis://localhost:6379/0'),
    task_serializer='json',
    result_serializer='json',
    accept_content=['json'],
    task_acks_late=True,
    worker_prefetch_multiplier=1,
    task_reject_on_worker_lost=True,
    task_max_retries=3,
    task_default_retry_delay=60,
    result_expires=3600,
    timezone='Asia/Hong_Kong',
    enable_utc=True,
)

Django settings

<code"># settings.py
CELERY_BROKER_URL = env('REDIS_URL')
CELERY_RESULT_BACKEND = env('REDIS_URL')

# myapp/__init__.py
from .celery import app as celery_app
__all__ = ('celery_app',)

Step 3: Define Tasks

<code"># myapp/tasks.py
from celery import shared_task
from celery.utils.log import get_task_logger

logger = get_task_logger(__name__)

@shared_task(bind=True, max_retries=3, default_retry_delay=60, queue='email')
def send_order_confirmation(self, order_id: int, customer_email: str):
    """Send order confirmation email — retries up to 3 times."""
    try:
        from .models import Order
        from django.core.mail import send_mail

        order = Order.objects.get(id=order_id)
        send_mail(
            subject=f'Order Confirmation #{order.order_number}',
            message=f'Your order {order.order_number} has been confirmed.',
            from_email='orders@yourdomain.com',
            recipient_list=[customer_email],
        )
        logger.info(f'Confirmation sent for order {order_id}')

    except Exception as exc:
        logger.error(f'Failed: {exc}')
        raise self.retry(exc=exc)


@shared_task(queue='media', time_limit=120, soft_time_limit=90)
def process_uploaded_image(image_path: str, user_id: int):
    """Resize and optimise uploaded image to WebP, upload to MinIO."""
    from PIL import Image
    import boto3, io

    s3 = boto3.client('s3', endpoint_url='https://storage.yourdomain.com')

    with Image.open(image_path) as img:
        for size_name, dims in {'thumb': (150,150), 'medium': (600,600)}.items():
            resized = img.copy()
            resized.thumbnail(dims, Image.LANCZOS)
            buf = io.BytesIO()
            resized.save(buf, format='WEBP', quality=85)
            buf.seek(0)
            s3.upload_fileobj(buf, 'app-uploads', f'users/{user_id}/{size_name}.webp')

    return {'status': 'processed'}


@shared_task
def cleanup_expired_sessions():
    from django.contrib.sessions.backends.db import SessionStore
    SessionStore.clear_expired()
    logger.info('Expired sessions cleaned')

Step 4: Enqueue Tasks from Views

<code"># Fire and forget — returns immediately, no blocking
def create_order(request):
    order = Order.objects.create(...)
    send_order_confirmation.delay(order.id, request.user.email)
    return JsonResponse({'order_id': order.id})

# Delayed execution (run in 5 minutes)
send_order_confirmation.apply_async(
    args=[order.id, email],
    countdown=300
)

# Scheduled for specific time
send_order_confirmation.apply_async(
    args=[order.id, email],
    eta=datetime.utcnow() + timedelta(hours=1)
)

# Check task status
from celery.result import AsyncResult
r = AsyncResult(task_id)
print(r.status)   # PENDING / SUCCESS / FAILURE
print(r.result)   # Return value

Step 5: Systemd Services

<code">cat > /etc/systemd/system/celery-worker.service << 'EOF' [Unit] Description=Celery Worker After=network.target redis.service [Service] Type=forking User=myapp WorkingDirectory=/opt/myapp EnvironmentFile=/opt/myapp/.env ExecStart=/opt/myapp/venv/bin/celery \ -A myapp worker \ --loglevel=info \ --concurrency=4 \ --queues=default,email,media \ --pidfile=/tmp/celery-worker.pid \ --logfile=/var/log/myapp/celery-worker.log \ --detach ExecStop=/opt/myapp/venv/bin/celery -A myapp control shutdown PIDFile=/tmp/celery-worker.pid Restart=always [Install] WantedBy=multi-user.target EOF cat > /etc/systemd/system/celery-beat.service << 'EOF'
[Unit]
Description=Celery Beat Scheduler
After=network.target redis.service celery-worker.service

[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/.env
ExecStart=/opt/myapp/venv/bin/celery \
    -A myapp beat \
    --loglevel=info \
    --scheduler django_celery_beat.schedulers:DatabaseScheduler
Restart=always

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now celery-worker celery-beat

Step 6: Flower — Task Monitoring UI

<code">cat > /etc/systemd/system/celery-flower.service << 'EOF'
[Unit]
Description=Celery Flower Monitor
After=network.target

[Service]
Type=simple
User=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/opt/myapp/.env
ExecStart=/opt/myapp/venv/bin/celery \
    -A myapp flower \
    --port=5555 \
    --address=127.0.0.1 \
    --basic_auth=admin:StrongFlowerPass!
Restart=always

[Install]
WantedBy=multi-user.target
EOF

systemctl enable --now celery-flower

Flower UI at https://yourdomain.com/flower/ shows active workers, task history, success/failure rates, and queue depths in real time.


Queue Strategy

QueueWorkersTasks
default4General background tasks
email2Email sending
media2Image/video processing
critical2Payments, urgent notifications

Conclusion

Celery on a Hong Kong VPS with Redis transforms synchronous bottlenecks into fast async operations — emails, image processing, report generation, and external API calls all move off the critical request path. Redis running on the same VPS keeps task enqueue latency under 1ms, Celery Beat handles scheduled jobs, and Flower provides operational visibility. A 4 GB VPS runs Django/FastAPI, Celery workers, Redis, and PostgreSQL together for most production workloads.

Process jobs async: Browse Server.HK Hong Kong VPS plans — a 4 GB plan handles the full async stack alongside your web application.

Recent Posts

  • Monorepo Deployment on Hong Kong VPS: Turborepo and pnpm (2026)
  • GitLab Runner on Hong Kong VPS: Self-Hosted CI/CD Pipeline (2026)
  • Deploy Spring Boot on Hong Kong VPS: Java Microservices for Asia (2026)
  • TimescaleDB on Hong Kong VPS: Time-Series Data for Asia-Pacific (2026)
  • Hong Kong VPS China Accessibility Checklist: Make Your Site Work (2026)

Recent Comments

  1. Hong Kong VPS Uptime and SLA: What 99.9% Uptime Really Means for Your Business (2026) - Server.HK on How to Monitor Your Hong Kong VPS: Uptime, Performance, and Alert Setup Guide (2026)
  2. Best Hong Kong VPS Providers in 2026: Compared by Speed, Routing, and Value - Server.HK on How to Migrate Your Website to a Hong Kong VPS: Zero-Downtime Transfer Guide (2026)
  3. vibramycin injection on How to Choose the Right Hong Kong VPS Plan: A Buyer’s Guide for 2026
  4. allopurinol for gout on CN2 GIA vs BGP vs CN2 GT: What’s the Real Difference for China Connectivity?
  5. antibiotics online purchase on How to Set Up a WordPress Site on a Hong Kong VPS with aaPanel (Step-by-Step 2026)

Knowledge Base

Access detailed guides, tutorials, and resources.

Live Chat

Get instant help 24/7 from our support team.

Send Ticket

Our team typically responds within 10 minutes.

logo
Alipay Cc-paypal Cc-stripe Cc-visa Cc-mastercard Bitcoin
Cloud VPS
  • Hong Kong VPS
  • US VPS
Dedicated Servers
  • Hong Kong Servers
  • US Servers
  • Singapore Servers
  • Japan Servers
More
  • Contact Us
  • Blog
  • Legal
© 2026 Server.HK | Hosting Limited, Hong Kong | Company Registration No. 77008912
Telegram
Telegram @ServerHKBot