ACE-Step UI Backend Technology Stack: Node.js, Express, and SQLite Architecture
ACE-Step UI runs on a lightweight Node.js backend built with TypeScript and Express 4.18, using SQLite for data persistence, JWT for authentication, and node-cron for scheduled maintenance tasks.
The ACE-Step UI project (fspecii/ace-step-ui) provides a self-contained web interface for AI music generation. Its backend technology stack prioritizes simplicity and local deployment, requiring only Node.js v20+ to run the entire API server without external database dependencies.
Core Runtime and Framework
The foundation of the ACE-Step UI backend rests on three core technologies that handle request processing, type safety, and server logic.
Node.js v20+ with TypeScript
The server executes on Node.js v20+, compiled from TypeScript sources defined in server/tsconfig.json. This combination provides modern JavaScript features alongside static typing, catching errors during compilation rather than at runtime. The TypeScript configuration targets ES2022, ensuring compatibility with contemporary Node.js features while maintaining broad support.
Express 4.18 Web Framework
Express 4.18 powers the HTTP layer, handling routing, middleware chaining, and static asset delivery. In server/src/index.ts, the application bootstrap configures essential middleware before mounting route handlers:
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import { config } from './config/index.js';
const app = express();
app.use(helmet());
app.use(cors({ origin: config.frontendUrl, credentials: true }));
app.use(express.json());
app.get('/health', (_req, res) => res.json({ status: 'ok' }));
app.listen(config.port, '0.0.0.0', () => {
console.log(`Server listening on http://localhost:${config.port}`);
});
This configuration implements security headers via helmet, enables cross-origin requests through cors, and parses JSON payloads using Express's built-in middleware.
Data Layer: SQLite with better-sqlite3
Rather than requiring a separate database server, ACE-Step UI uses SQLite via the better-sqlite3 package, creating a file-based relational store at server/data/ace-step.db. This approach makes the backend truly self-contained, ideal for local installations or small cloud deployments.
The database connection is centralized in server/src/db/pool.ts:
import Database from 'better-sqlite3';
import path from 'path';
const dbPath = path.resolve(__dirname, '../../data/ace-step.db');
export const db = new Database(dbPath);
// Example query
export const getUserById = (id: string) =>
db.prepare('SELECT * FROM users WHERE id = ?').get(id);
better-sqlite3 offers synchronous, high-performance access to SQLite, suitable for the single-user or low-concurrency scenarios typical of local AI tooling setups.
Authentication and Security
JWT-Based Stateless Auth
The stack implements JSON Web Tokens (JWT) via the jsonwebtoken library for stateless authentication. When a user completes the setup flow, the server issues a signed token in server/src/routes/auth.ts:
import jwt, { SignOptions } from 'jsonwebtoken';
import { config } from '../config/index.js';
const jwtOptions: SignOptions = { expiresIn: config.jwt.expiresIn };
function issueAccessToken(payload: { id: string; username: string }) {
return jwt.sign(payload, config.jwt.secret, jwtOptions);
}
Protected routes throughout the API verify these tokens using middleware defined in server/src/middleware/auth.ts, extracting the user identity from the JWT payload without maintaining server-side session storage.
Security Middleware
Beyond JWT, the stack layers helmet for HTTP header security and cors for origin control, both configured in server/src/index.ts. The dotenv package loads sensitive configuration—such as JWT secrets and API keys—from .env files, keeping credentials out of the source code.
External Service Integration
ACE-Step UI communicates with several external AI and media services through dedicated client libraries listed in server/package.json:
- @gradio/client: Connects to the ACE-Step music generation API
- @google/genai: Interfaces with Google Gemini for additional AI capabilities
- @ffmpeg/ffmpeg: Handles server-side audio processing and media transcoding
These integrations allow the Node.js backend to orchestrate complex AI workflows while presenting a unified REST API to the frontend.
Task Scheduling with node-cron
Maintenance operations run automatically via node-cron, which schedules cleanup jobs to prevent disk bloat from orphaned audio files. The scheduler configuration in server/src/index.ts triggers daily at 3:00 AM:
import cron from 'node-cron';
import { runCleanupJob, cleanupDeletedSongs } from './services/cleanup.js';
cron.schedule('0 3 * * *', async () => {
console.log('Running scheduled cleanup job...');
await runCleanupJob();
await cleanupDeletedSongs();
});
The cleanup logic itself resides in server/src/services/cleanup.ts, removing database entries for deleted songs and purging associated audio files from storage.
Summary
- Runtime: Node.js v20+ with TypeScript compilation
- Web Framework: Express 4.18 handling routing and middleware
- Database: SQLite via better-sqlite3 for file-based data persistence
- Authentication: JWT tokens issued via jsonwebtoken
- Security: helmet headers, cors policies, and dotenv configuration
- Integrations: Gradio client, Google GenAI, and FFmpeg for AI/media processing
- Scheduling: node-cron for automated maintenance tasks
This architecture creates a portable, low-overhead backend suitable for local development or lightweight production deployments.
Frequently Asked Questions
Does ACE-Step UI require a separate database server like PostgreSQL or MySQL?
No. The backend uses SQLite via the better-sqlite3 package, storing all data in a single file (ace-step.db). This eliminates the need for separate database infrastructure, making the application fully self-contained and easier to deploy on minimal hardware.
Why was TypeScript chosen over JavaScript for the backend?
TypeScript provides static type checking and modern language features that catch errors during compilation. According to the repository's tsconfig.json, the project targets ES2022 with strict type checking, improving code maintainability and reducing runtime errors in the Express application.
How does the backend handle authentication without server-side sessions?
The stack uses JSON Web Tokens (JWT) for stateless authentication. When a user logs in, the server issues a signed JWT containing the user ID and username. Subsequent requests include this token in the Authorization header, which middleware in server/src/middleware/auth.ts verifies against the configured secret, eliminating the need for session storage.
What triggers the automated cleanup of audio files?
node-cron schedules a daily cleanup job at 3:00 AM UTC, defined in server/src/index.ts. This job executes functions from server/src/services/cleanup.ts to remove orphaned audio files and purge soft-deleted song records from the SQLite database, preventing unlimited disk growth.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →