FractalCore and the hard part of federated Android fleets
The central nervous system and backend orchestrator for Fractal. It handles multi-tenant task scheduling, real-time TFLOPs budgeting, and federated weight aggregation using FedAvg.
At a glance
- What is it?
- FractalCore is the central server for the Fractal ecosystem, doing two jobs at once: scheduling federated training rounds across Android nodes and slicing foundation models into mobile-ready partitions. The architecture is well described, the release history is thin, and the licence rules out commercial use.
- Who is it for?
- FractalCore suits a research group running its own Android fleet for federated training and on-device model work, and it does not suit a commercial deployment because the badge names a proprietary non-commercial licence. Before adopting it, read LICENSE, confirm that the .env copy of ADMIN_PASSWORD is replaced, and check that your Firestore service account path matches FIREBASE_SERVICE_ACCOUNT_PATH.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 62 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Two jobs behind one Flask gateway
FractalCore is the central server and control plane for the Fractal decentralized compute ecosystem, and the project describes itself as the central nervous system and backend orchestrator. What makes it unusual is that one repository carries two fairly different workloads. The first is federated learning orchestration: multi-tenant data binning, task scheduling, client checkpoint verification, and deterministic parameter aggregation through Federated Averaging. The second is foundation model slicing, described as offline neural graph surgery that produces memory-safe .pte layer partitions for mobile nodes.
The clients are Android devices running what the repository calls FractalAndroid. Those devices are the compute pool, and they are where both halves of the project end up: they receive training tasks in a federated round, and they receive compiled model partitions to run inference locally.
The audience is fairly specific. A team that owns a fleet of Android hardware, wants to train on data that stays on those devices, and also wants to deploy a large model to them under a tight memory budget is the intended user. A team that just wants to train one model on one server does not need a control plane with tenants, quota gauges and a reward ledger, and the single-user server referenced in the deployment files exists for exactly that lighter case.
There is also a money-shaped element. The reward interface credits compute tokens called Liquid MBs to user profiles in Google Cloud Firestore after a checkpoint passes verification, so the system is built around the idea that device owners are compensated for contributing compute.
How a request travels through the control plane
The architecture section is explicit about how the pieces connect, and the wiring is worth reading closely because it explains most of the design choices. The REST gateway and route handlers sit in front, and Android nodes talk to it over REST HTTPS carrying an X-Auth-Token header for task and checkpoint traffic.
Behind the gateway the path is linear: the session manager authenticates, the multi-tenant isolation manager resolves the tenant, the task queue and segment dispatcher hand work to available Android nodes and write to disk storage, and the FedAvg engine pulls uploaded checkpoints and writes aggregated weights back. The reward processor is the one branch that leaves the local server, since it settles Liquid MBs into Firestore.
State is split in two, which is the detail most likely to surprise an operator. Firestore holds tenants, devices and the ledger. Everything bulky stays on local disk silos laid out per tenant and username, covering bins, uploads and compiled global models. The multi-tenant orchestrator in src/fractal_server/server.py keeps those paths physically separated under data/tenants/{username}/, so two tenants cannot see each other's datasets or checkpoints by path alone.
Session isolation is token based rather than cookie based. Tokens are generated with secrets.token_hex(32) and held in a thread-safe registry, and the README highlights the absence of cookie leakage between browser tabs or clients. That design is a reasonable answer to a specific problem, since a shared kiosk browser running several tenant sessions is exactly where cookie based auth breaks.
FedAvg with a task registry, not a loose callback
The federated aggregation engine is where the design earns its keep. Dispatching does not hand arbitrary work to a node. It distributes ActiveTask objects that reference specific binary data bins, and the selection is based on hardware telemetry proofs reported by the device, so a node without the right capability is not a candidate.
Upload handling is the part with teeth. When a node returns a checkpoint, the server validates it against the active task registry, and only when the round threshold is reached does the engine execute FedAvg weight summation using TensorFlow and NumPy. The requirement for a tensor library at aggregation time is notable, since torch and torchao appear elsewhere in the project for the slicing pipeline, so the server pulls in two numerical stacks for different halves of the workflow. Once aggregated, the weights are serialized and archived, and the active model served to later rounds is updated.
Compute governance sits alongside that. Per-tenant TFLOPs limits are enforced, with capacity and round progression monitored in real time and surfaced in the dashboard as a quota gauge. This is a different design from a job queue that only checks whether a device is free, because a tenant can burn through a fixed compute allowance and be cut off, and the admin console can set those caps.
The undocumented edges are worth naming. The README does not describe how a node that misses a round is handled, whether late checkpoints are accepted, how FedAvg weights are merged when clients return checkpoints with different parameter shapes, or what happens to a round when a client uploads a corrupted file. None of that is answered in the files shown here, and each of those cases decides whether a training run converges.
Turning a Llama 3 8B into .pte partitions for Android
The model slicing compiler in src/inference-model-maker/slicer/ is the most unusual part of the repository. It ingests monolithic Hugging Face models, with Llama 3 8B and TinyLlama given as examples, and extracts isolated decoder transformer blocks without breaking weight references. The goal is to produce separate layer partitions, each small enough to sit comfortably in the memory of a phone.
The pipeline has four stages. INT4 quantization applies grouped weight-only quantization using torchao at group size 128, targeting linear attention and MLP projections, with a stated aim of pushing layer memory footprints below 150MB. Static ATen tracing freezes dynamic Python operations into static computational graphs through torch.export, which is what makes a block independently loadable. XNNPACK lowering then compiles to the ExecuTorch Edge dialect with XNNPACK microkernels, and the result is serialized into .pte binaries for zero-copy mmap ingestion on Android nodes.
That chain is a genuine engineering path rather than a packaging exercise. torch.export only works on operations that are traceable, so any dynamic control flow inside a block has to be resolved before the graph is frozen, and that constraint is the most likely source of friction when a new model does not fit. The zero-copy mmap detail matters for phones too, since it avoids loading a partition into the heap in full.
Quantization at group size 128 is a compromise, not a free win. It trades a small accuracy change for a memory change, and the project documents the group size and the target footprint but not the resulting quality on a given task, so anyone depending on the numbers has to measure them on the target hardware.
Bringing the server up with Docker Compose
The repository ships a Dockerfile and a docker-compose.yml, and the compose file is the clearest description of the runtime layout. The fractal-server service builds from the local Dockerfile, publishes port 5000, reads its environment from a .env file, and mounts four directories from the host for uploads, downloads, tenants and the global model, so state survives a container rebuild:
services:
fractal-server:
build: .
ports:
- "5000:5000"
env_file:
- .env
volumes:
- ./src/fractal_server/uploads:/app/src/fractal_server/uploads
- ./src/fractal_server/downloads:/app/src/fractal_server/downloads
- ./src/fractal_server/tenants:/app/src/fractal_server/tenants
- ./src/fractal_server/global_model:/app/src/fractal_server/global_model
restart: unless-stoppedThe image is built from python:3.11-slim, installs the system build tools, installs the Python dependencies from requirements.txt, and creates the four runtime directories that the compose file then mounts over. The entrypoint is gunicorn with four workers and a 120 second timeout:
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "--timeout", "120", "src.fractal_server.server:app"]Configuration comes from a .env file, and the .env.example in the repository is the starting point. It defines the Flask app path and debug flags, an admin username and password, the path to a Firebase service account JSON file, and the host and port:
FLASK_APP=src/fractal_server/server.py
FLASK_ENV=development
FLASK_DEBUG=1
SECRET_KEY=generate-a-secure-key-here
ADMIN_USERNAME=admin
ADMIN_PASSWORD=orchestrate
FIREBASE_SERVICE_ACCOUNT_PATH=secrets/firebase/service-account.json
PORT=5000
HOST=0.0.0.0Two of those defaults are worth flagging before anyone copies the file across. ADMIN_PASSWORD ships as the literal word orchestrate, and SECRET_KEY ships as a placeholder string, so a deployment that keeps them is running with a public admin credential. The Python dependencies are a short, unglamorous list:
flask
flask-cors
tensorflow>=2.15.0
numpy
firebase-admin
google-cloud-firestore
python-dotenv
pathlib
typing-extensions
gunicornNote that the Docker image pins Python 3.11 while requirements.txt asks for tensorflow>=2.15.0, and the torch and torchao libraries used by the slicing compiler are not in that list, so the slicing stage has dependencies that the base image does not install. The compose file also carries a commented-out single-user service on port 5001 that runs src/experimental/single_user_server/server.py, which is the documented lighter path.
The operational gaps in an orchestration server
An orchestration server is judged on what happens when things break, and the visible documentation says little about that. There is a SECURITY.md, a CHANGELOG.md, a ROADMAP.md, a SUPPORT.md and a scripts/ directory at the top level of the repository, and the README claims a security-hardened posture, but the documentation does not describe key rotation for the token registry, audit logging, rate limiting on the REST gateway, or how a revoked tenant is purged from local silos. Token isolation is described in terms of what it prevents between sessions, not in terms of what happens to a leaked token.
The federated side has its own gap. Round threshold semantics, checkpoint schema validation beyond a registry lookup, and behavior for a device that never reports back are not spelled out. A single missing participant in FedAvg changes the effective averaging, so a documented policy on partial rounds would matter to anyone reading a training curve.
The claim that deserves the most scrutiny is the TFLOPs budget. The dashboard shows a live quota gauge and the admin console sets caps, and MB reward rates sit next to them, but the unit accounting behind TFLOPs is not defined in the visible files. Whether a cap counts the work a node reports, the work a node claims, or the work the server estimates changes the meaning of every number on that screen.
None of this makes the project unusable, but it does mean the adoption question is really a question about your own tolerance for reading source. For a server that sits between devices and a reward ledger, that is a fair amount of reading.
A proprietary non-commercial licence and no tagged releases
The licence is the clearest boundary in the project. The README badge names a Proprietary Non-Commercial v3.0 licence in the LICENSE file, and the packaging metadata classifies it as Other, which is GitHub's way of saying a custom licence that does not map to a standard one. This is not legal advice, but the practical reading is straightforward: a non-commercial licence excludes running this as a product or as a paid service, whatever the deployment looks like. Anyone evaluating it for a company has to resolve that before writing a line of integration code.
On maintenance, the repository is not archived and the last push was on 2026-08-22. The version badge in the README reads 1.0.0 and follows semantic versioning, but the project has no GitHub releases, so there is no tag to pin a deployment to. In practice the CHANGELOG.md file is the only version record visible from the top level, and the compose file pins no image digest, since the build is local rather than pulled from a registry. A deployment therefore tracks whatever the working tree happens to contain on the day it is built, which is a weak guarantee for a server that stores checkpoints and tenant data.
The project is also tightly coupled to Google Cloud services through firebase-admin and google-cloud-firestore, and the reward settlement path writes into Firestore. Running a local experimental deployment still requires a service account JSON at FIREBASE_SERVICE_ACCOUNT_PATH, so the Firebase dependency is present even when the reward path is not the interesting part of the work.
Editorial conclusion
FractalCore suits a research group running its own Android fleet for federated training and on-device model work, and it does not suit a commercial deployment because the badge names a proprietary non-commercial licence. Before adopting it, read LICENSE, confirm that the .env copy of ADMIN_PASSWORD is replaced, and check that your Firestore service account path matches FIREBASE_SERVICE_ACCOUNT_PATH.
Frequently asked questions
How do I run FractalCore locally?
Copy .env.example to .env and fill in the values, then build and start the fractal-server service with docker-compose.yml, which publishes port 5000 and mounts the uploads, downloads, tenants and global_model directories. The image is python:3.11-slim and starts gunicorn with four workers against src.fractal_server.server:app.
What does FractalCore do for federated learning on Android devices?
It is the control plane that bins data per tenant, dispatches ActiveTask objects referencing binary bins to FractalAndroid nodes based on hardware telemetry, validates uploaded checkpoints against the active task registry, and runs FedAvg weight summation with TensorFlow and NumPy when the round threshold is reached. Aggregated weights are archived and become the model served to later rounds.
How does the model slicer turn a foundation model into something an Android node can load?
The compiler in src/inference-model-maker/slicer/ ingests a Hugging Face model such as Llama 3 8B, extracts isolated decoder blocks, applies torchao INT4 weight-only quantization at group size 128, freezes the graph with torch.export, lowers to the ExecuTorch Edge dialect with XNNPACK microkernels, and writes .pte binaries that Android nodes mmap in zero-copy. The stated aim is layer memory footprints below 150MB.
Can I use FractalCore in a commercial product?
The project ships under a Proprietary Non-Commercial v3.0 licence in the LICENSE file, and the repository metadata classifies it as Other rather than a standard permissive licence. Read the LICENSE file yourself, and treat the non-commercial term as a boundary to resolve with your own counsel before any paid use.
Is FractalCore still being worked on and can I pin a version?
The repository is not archived and the last push was on 2026-08-22, but it has no GitHub releases, so there is no tag to pin. The README badge shows version 1.0.0 and the CHANGELOG.md file at the top level is the only version record available from the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/fractal-compute-orchestrations-fractalcore)Was this useful?