Multi-Component Applications
Learn how to deploy applications with multiple interconnected services using Flux's internal DNS system
What You'll Learn
Before You Start
- ✓ Completed the Basic Deployment tutorial
 - ✓ Understand Docker networking basics
 - ✓ Familiar with environment variables
 - ✓ Have FLUX tokens (~calculating... FLUX for this tutorial)
 
Understanding Flux Internal DNS
When you deploy a multi-component app on Flux, each component can communicate with others using a special internal DNS pattern:
Example: For an app named "mystack" with components:
- • 
database→ accessible atfluxdatabase_mystack:5432 - • 
api→ accessible atfluxapi_mystack:3000 - • 
frontend→ accessible atfluxfrontend_mystack:8080 
Plan Your Multi-Component Architecture
Let's build a simple web application stack with three components:
PostgreSQL Database
Stores application data
Port: 5432
Node.js API
Backend REST API
Port: 3000
React Frontend
User interface
Port: 8080
Communication Flow:
Create the API Component
Create a Node.js API that connects to PostgreSQL:
const express = require('express');
const { Pool } = require('pg');
const app = express();
const PORT = process.env.PORT || 3000;
// Database connection using Flux internal DNS
const pool = new Pool({
  host: process.env.DB_HOST,
  port: 5432,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
});
app.use(express.json());
// Health check
app.get('/health', async (req, res) => {
  try {
    await pool.query('SELECT 1');
    res.json({ status: 'healthy', database: 'connected' });
  } catch (error) {
    res.status(500).json({ status: 'unhealthy', error: error.message });
  }
});
// Get all items
app.get('/api/items', async (req, res) => {
  try {
    const result = await pool.query('SELECT * FROM items ORDER BY created_at DESC');
    res.json(result.rows);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
// Create item
app.post('/api/items', async (req, res) => {
  try {
    const { name, description } = req.body;
    const result = await pool.query(
      'INSERT INTO items (name, description) VALUES ($1, $2) RETURNING *',
      [name, description]
    );
    res.json(result.rows[0]);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
app.listen(PORT, '0.0.0.0', () => {
  console.log(`API server running on port ${PORT}`);
  console.log(`Database host: ${process.env.DB_HOST}`);
});docker build -t yourusername/mystack-api:latest ./api
docker push yourusername/mystack-api:latestCreate the Frontend Component
Create a simple React frontend that calls the API:
import { useState, useEffect } from 'react';
function App() {
  const [items, setItems] = useState([]);
  const [name, setName] = useState('');
  const [description, setDescription] = useState('');
  // API URL from environment variable
  const API_URL = process.env.REACT_APP_API_URL || 'http://localhost:3000';
  useEffect(() => {
    fetchItems();
  }, []);
  const fetchItems = async () => {
    try {
      const response = await fetch(`${API_URL}/api/items`);
      const data = await response.json();
      setItems(data);
    } catch (error) {
      console.error('Error fetching items:', error);
    }
  };
  const addItem = async (e) => {
    e.preventDefault();
    try {
      await fetch(`${API_URL}/api/items`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ name, description }),
      });
      setName('');
      setDescription('');
      fetchItems();
    } catch (error) {
      console.error('Error adding item:', error);
    }
  };
  return (
    <div className="App">
      <h1>My Flux App</h1>
      <form onSubmit={addItem}>
        <input
          type="text"
          value={name}
          onChange={(e) => setName(e.target.value)}
          placeholder="Name"
          required
        />
        <input
          type="text"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          placeholder="Description"
        />
        <button type="submit">Add Item</button>
      </form>
      <ul>
        {items.map((item) => (
          <li key={item.id}>
            <strong>{item.name}</strong>: {item.description}
          </li>
        ))}
      </ul>
    </div>
  );
}
export default App;docker build -t yourusername/mystack-frontend:latest ./frontend
docker push yourusername/mystack-frontend:latestCreate Multi-Component Deployment Spec
Now create a deployment spec that ties all three components together:
{
  "version": 8,
  "name": "mystack",
  "description": "Multi-component web application stack",
  "owner": "YOUR_ZELID_HERE",
  "instances": 3,
  "staticip": false,
  "enterprise": "",
  "compose": [
    {
      "name": "database",
      "description": "PostgreSQL database",
      "repotag": "postgres:16-alpine",
      "ports": [5432],
      "containerPorts": [5432],
      "domains": [""],
      "environmentParameters": [
        "POSTGRES_DB=myapp",
        "POSTGRES_USER=myuser",
        "POSTGRES_PASSWORD=mypassword"
      ],
      "commands": [],
      "containerData": "/var/lib/postgresql/data",
      "cpu": 1.0,
      "ram": 2000,
      "hdd": 20,
      "tiered": false
    },
    {
      "name": "api",
      "description": "Node.js API server",
      "repotag": "yourusername/mystack-api:latest",
      "ports": [3000],
      "containerPorts": [3000],
      "domains": [""],
      "environmentParameters": [
        "PORT=3000",
        "DB_HOST=fluxdatabase_mystack",
        "DB_NAME=myapp",
        "DB_USER=myuser",
        "DB_PASSWORD=mypassword"
      ],
      "commands": [],
      "containerData": "/appdata",
      "cpu": 1.0,
      "ram": 2000,
      "hdd": 10,
      "tiered": false
    },
    {
      "name": "frontend",
      "description": "React frontend",
      "repotag": "yourusername/mystack-frontend:latest",
      "ports": [8080],
      "containerPorts": [8080],
      "domains": [""],
      "environmentParameters": [
        "REACT_APP_API_URL=http://fluxapi_mystack:3000"
      ],
      "commands": [],
      "containerData": "/appdata",
      "cpu": 0.5,
      "ram": 1000,
      "hdd": 5,
      "tiered": false
    }
  ]
}Key Points
- • API connects to database using 
fluxdatabase_mystack - • Frontend connects to API using 
fluxapi_mystack:3000 - • All components share the same app name: 
mystack - • Database gets persistent storage for data survival
 
Deploy and Verify Communication
Deploy your multi-component stack to Flux:
- 1
Go to home.runonflux.io and paste your spec
 - 2
Review the total cost (~calculating... FLUX/month for all 3 components)
 - 3
Deploy and wait 5-10 minutes for all components to start
 - 4
Test API health to verify database connection:
curl https://mystack-api-abc123.app.runonflux.io/health - 5
Access frontend and verify it can communicate with API
 
Troubleshooting Component Communication:
- • Make sure component names in spec match the DNS pattern
 - • Check environment variables are set correctly
 - • Verify all components are in "Running" state
 - • Look at container logs for connection errors
 
Best Practices
🔒 Security
- • Don't expose database ports publicly (Flux handles this automatically)
 - • Use strong passwords for databases
 - • Consider using Enterprise mode for private images with secrets
 
💾 Data Persistence
- • Always set 
containerDatafor databases - • Allocate sufficient HDD space for data growth
 - • Test backups before going to production
 
⚡ Performance
- • Start components in order: database → backend → frontend
 - • Add health check endpoints to all components
 - • Monitor resource usage and scale appropriately