This release is a pre-release and may not be stable for production use.
A composable architectural foundation for building scalable applications on top of FastAPI.
Standardize your structure, manage atomic transactions, and protect sensitive data — without sacrificing FastAPI's flexibility.
🧭 Overview
FastAPI is an exceptional microframework for HTTP routing, request parsing, and asynchronous I/O.
However, as applications grow into medium and large systems, teams inevitably encounter an architectural gap:
- Database sessions leak across asynchronous tasks or background jobs.
- Business workflows spanning multiple repositories lack reliable, all-or-nothing transaction boundaries.
- Teams end up writing dozens of nearly identical DTO schemas just to hide internal fields (like profit margins, supplier terms, or sensitive IDs) from different user roles.
- Domain modules become tightly coupled through circular imports and tangled dependency trees.
Heavy enterprise frameworks solve these challenges by enforcing rigid conventions, proprietary ORMs, and heavy abstractions that eliminate your freedom.
ZCore is the middle ground: ZCore provides a structured, modular layer that sits directly on top of standard FastAPI, SQLAlchemy 2.0, and Pydantic V2. It introduces proven architectural patterns (Unit of Work, IoC Dependency Injection, Field-Level Security, and Domain Event Dispatching) as composable building blocks.
Your code remains 100% standard FastAPI. Adopt ZCore piece by piece where it solves real problems, or use the full architectural stack — with zero vendor lock-in.
🛍️ Reference Showcase: ZShop
To see ZCore's architectural concepts in action before writing a single line of code, explore ZShop — the official Modular Monolith e-commerce reference implementation:
- Interactive Live Inspector Dock: Monitor active request context, correlation IDs (
x-request-id), execution latencies, and real-time SSE stream events. - 1-Click RBAC Persona Switcher: Switch between SuperAdmin, Store Manager, Customer, and Guest to watch confidential data fields automatically vanish from responses via
Zchema. - Atomic Rollback Demonstration: An interactive deficit checkout button verifying that stock adjustments and order persistence roll back atomically when any invariant fails.
- Decoupled Architecture: Strict inter-module communication using Python Protocols (
ProductContract) without cross-domain database coupling.
👉 Explore the ZShop Showcase Repository
⚖️ Why ZCore? (An Honest Comparison)
| Architectural Concern | Plain FastAPI | Full-Stack Monoliths (e.g. Django) | With ZCore on FastAPI |
|---|---|---|---|
| Application Philosophy | Minimalist microframework; no opinion on database, folders, or architecture. | Opinionated, batteries-included; tightly coupled to its own ORM and template engine. | Composable layer; provides enterprise architecture patterns while keeping FastAPI completely standard. |
| Role-Based Data Exposure | Writing multiple Pydantic models per role (UserPublic, UserAdmin) or manual if/else checks. |
Model-level permissions or custom serializer logic. | Single-schema context shielding (Zchema); forbidden fields are pruned dynamically from validation, serialization, and OpenAPI. |
| Multi-Repository Operations | Scattered session.commit() calls; high risk of partial writes on failure. |
Managed transaction blocks (transaction.atomic()). |
Re-entrant UnitOfWork; coordinated all-or-nothing boundaries with domain events deferred until physical commit succeeds. |
| Background Processing | Passing request sessions to background tasks often leads to Session is closed errors. |
Requires external queue workers (Celery, RQ) even for simple background jobs. | Dedicated @background_task; automatically isolates DB sessions and IoC lifecycles from completed HTTP requests. |
| Domain Modularity | Standard APIRouters; easily slips into spaghetti code and circular imports at scale. | Django Apps with rigid settings and global app registries. | DAG-driven Plugin system; topological startup sorting and pure Python Protocol contracts for zero-coupling. |
| Dataset Pagination | Manual offset / limit SQL slicing that degrades on large tables. |
Built-in offset paginators. | Keyset Cursor Pagination (Base64); zero-drift pagination and dynamic AST-like JSON search engine. |
| Testing Isolation | Manual DB cleanup routines or slow schema recreation per test file. | TransactionTestCase rolling back transactions per test. | Zero-side-effect ZTestClient; automated savepoint rollbacks, context mocking, and container sandboxing. |
🚀 Quick Start (in Under 60 Seconds)
1. Installation
pip install "fastapi-zcore-framework[all]"
2. Scaffold a New Project
The interactive zc CLI configures your environment, sets up a virtual environment (uv or pip), and provisions your database driver:
# Interactive mode (recommended)
zc init core_api && cd core_api
# Generate your first domain module
zc startapp tasks
3. Define Your Domain Model
Open tasks/models.py (standard SQLAlchemy 2.0):
import uuid
from sqlalchemy.orm import Mapped, mapped_column
from zcore import Base, SoftDeleteMixin
class Task(Base, SoftDeleteMixin):
__tablename__ = "tasks"
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
title: Mapped[str] = mapped_column(index=True)
is_completed: Mapped[bool] = mapped_column(default=False)
4. Run the Development Server
zc run
Your API is running at http://127.0.0.1:8000 with 8 production-ready endpoints out of the box:
POST /tasks/— Create entityGET /tasks/{id}— Fetch single record (with automatic PK type inspection)GET /tasks/— List records (with cursor or offset pagination)POST /tasks/search— Dynamic nested JSON filtering enginePOST /tasks/lookup— Lightweight field-projected endpoint for dropdownsPUT /tasks/{id}&PATCH /tasks/{id}— Full and partial updatesDELETE /tasks/{id}— Soft delete (or permanent purge via?force=true)GET /tasks/?schema=true— Dynamic role-aware frontend form schema
🏛️ Core Architectural Patterns
1. Context Shielding & Role-Based Field Pruning (Zchema)
The Problem
In enterprise applications, different roles require different views of the same data. A Customer must not see wholesale cost prices or internal supplier notes, while a Store Manager requires full financial transparency. Maintaining separate DTOs (ProductPublic, ProductManager, ProductCreate, ProductAdminUpdate) creates boilerplate and maintenance overhead.
The ZCore Solution
Define your model once inheriting from Zchema. When a user's security context marks a field as restricted, ZCore automatically prunes it across input parsing (preventing mass assignment), response serialization (preventing data leakage), and OpenAPI schema generation:
import uuid
from decimal import Decimal
from pydantic import Field
from zcore import Zchema
class ProductResponse(Zchema):
__model__ = "products"
id: uuid.UUID
name: str
price: Decimal
cost_price: Decimal | None = None # 🔒 Sensitive business margin
supplier_notes: str | None = None # 🔒 Internal agreement details
- When a Customer views the product:
cost_priceandsupplier_notesare completely omitted from the JSON output. ZCore automatically attaches aVary: Authorization, Cookieheader to protect downstream CDNs from cache poisoning. - When a Manager views the product: All fields are returned transparently.
2. Atomic Unit of Work & Deferred Domain Events (UnitOfWork)
The Problem
In distributed or multi-repository architectures, business actions involve multiple persistence steps (e.g., deducting inventory, recording a purchase order, and generating an invoice). If step 2 fails, step 1 must be reverted. Furthermore, if you send an email or emit a domain event before the database commit succeeds, a subsequent failure leaves external systems out of sync.
The ZCore Solution
ZCore implements a re-entrant, depth-aware UnitOfWork. Nested transactions safely flush changes to savepoints without prematurely committing, while domain events are buffered and dispatched only after the root commit succeeds:
from zcore import UnitOfWork
async with UnitOfWork(session=self.session, dispatcher=self.dispatcher) as uow:
# 1. Adjust inventory
await self.inventory_service.adjust_stock(product_id, -quantity)
# 2. Persist order
self.order_repo.add(new_order)
await self.session.flush()
# 3. Buffer domain event
# If the transaction rolls back, this event is discarded immediately!
uow.register_event("order.created", {"order_id": str(new_order.id)})
3. Contract-Driven Decoupling via Inversion of Control (IoC Container)
The Problem
Modular monoliths frequently suffer from circular imports when domain A (e.g., Orders) needs data from domain B (e.g., Catalog). Importing repositories or models across module boundaries creates tight database coupling.
The ZCore Solution
Domains communicate strictly through pure Python Protocols (Contracts). The IoC Container auto-wires dependencies at runtime using constructor type hints with signature caching:
# contracts/catalog.py (No database imports!)
from typing import Protocol, runtime_checkable
@runtime_checkable
class ProductContract(Protocol):
async def adjust_stock(self, product_id: str, delta: int) -> None: ...
# apps/orders/services.py
from contracts.catalog import ProductContract
class OrderService(BaseService[Orders]):
# Pure Python constructor: Auto-wired by ZCore's IoC container!
def __init__(self, repository: OrderRepository, inventory: ProductContract):
super().__init__(model=Orders, repository=repository)
self.inventory = inventory
4. Isolated Background Scopes (@background_task)
The Problem
FastAPI's built-in BackgroundTasks executes callables after sending the HTTP response. If you pass an active request-scoped database session to a background task, the session is closed by the time the worker executes, causing InterfaceError: Session is closed.
The ZCore Solution
The @background_task decorator creates an independent execution scope, provisions a dedicated database session, binds an isolated logging task ID, and auto-resolves annotated dependencies from the container:
from zcore import background_task
@background_task
async def generate_invoice_task(
order_id: uuid.UUID,
order_repo: OrderRepository, # Automatically injected with an isolated session!
) -> None:
order = await order_repo.get(id=order_id)
# Safely executes without relying on completed HTTP request lifecycles
5. Zero-Side-Effect Testing Engine (ZTestClient)
The Problem
Integration tests that write to a database require tedious teardown scripts or slow table recreation between test cases, leading to flaky test suites.
The ZCore Solution
ZTestClient executes tests inside transactional savepoint rollbacks. Changes are rolled back immediately upon test completion, keeping test runs fast and deterministic:
import pytest
from zcore.testing import ZTestClient
from main import app
@pytest.mark.asyncio
async def test_order_placement_atomicity():
async with ZTestClient(
app,
user_id="customer-uuid",
scopes=["orders:create", "products:view"]
) as client:
response = await client.post("/checkout/orders/", json={...})
assert response.status_code == 201
# Database is automatically rolled back to its exact pre-test state!
🛠️ Interactive Developer Tooling (zc CLI)
ZCore includes an interactive terminal user interface (TUI) powered by Questionary and Rich:
$ zc
⚡ ZCore Framework v0.1.0-rc.2 • Modern Modular Monolith
FastAPI • SQLAlchemy 2.0 • Pydantic V2
? What framework task would you like to perform?
❯ 🧩 startapp — Scaffold a modular domain app / plugin
⚡ run — Launch Uvicorn development server
📋 genenv — Generate template .env from Settings class
🔑 gensecret — Generate cryptographically secure SECRET_KEY
📦 init — Scaffold a new ZCore project
🚪 exit — Exit CLI
CLI Command Summary
| Command | Key Flags | Purpose |
|---|---|---|
zc |
— | Open interactive terminal dashboard |
zc init [name] |
--db [sqlite|postgres|mysql], -y |
Bootstrap project with .env, .venv, and driver dependencies |
zc startapp [name] |
--template / --no-template, --test, -y |
Generate domain module layers (models, schemas, repos, services, routers) |
zc run [app] |
--host, --port, --reload, --workers, --env-file |
Run server with cascading config hierarchy (CLI > .env > Defaults) |
zc gensecret |
— | Generate a 64-character cryptographic SECRET_KEY |
zc genenv |
-o <output>, -f / --force |
Introspect active Pydantic Settings and scaffold .env.example |
📢 Community Testing & Feedback (Release Candidate rc.2)
We are currently validating v0.1.0-rc.2 before tagging the official v1.0.0 stable release.
We built ZCore to solve architectural pain points we faced in production. Before declaring the API stable, we need your critical engineering feedback:
- Try the Showcase: Clone ZShop, run the seed script, and test the endpoints.
- Test the Edge Cases: Push the boundaries of
UnitOfWork, test complex nested queries withSearchEngine, or inspect field pruning withZchema. - Break It & Report: If an abstraction feels awkward, if a type hint breaks, or if an async session leaks, please open an issue!
👉 Submit Issues & Architectural Feedback on GitHub
📚 Documentation Index
Comprehensive guides, architectural deep-dives, and complete API references are available at our official documentation portal:
- Quick Start Tutorial — From zero to a working API in 60 seconds.
- 10-Step Quick Learn — Systematic layer-by-layer walkthrough.
- Architectural Comparisons — Honest comparisons with plain FastAPI, Django, and other frameworks.
- How-To Guides — Practical recipes for Multi-tenancy, Keyset Pagination, File Uploads, and Caching.
- Core Concepts — Deep dives into DI auto-wiring, Unit of Work, Kernel DAG, and Context shielding.
- API Reference — Detailed signatures and class specifications.
📄 License
ZCore Framework is open-source software licensed under the Apache License 2.0.
See the LICENSE file for details.
Developed with architectural rigor and care by Ali Alf Ostovar / Baseryn.
Metadata
Release files for fastapi-zcore-framework 0.1.0rc2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_zcore_framework-0.1.0rc2.tar.gz | 153.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_zcore_framework-0.1.0rc2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 271.0 kB
Release files / fastapi_zcore_framework-0.1.0rc2.tar.gz
| Download URL | fastapi_zcore_framework-0.1.0rc2.tar.gz |
|---|---|
| Size | 153.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
bfb7ff6ada7a28ded71986afbe788d1148a53808d7c8098dc36c90a3fe1bddff
|
|
BLAKE2b-256 checksum How to use checksums |
a3a9724f05f99a31c607e084ce80e5ec616ef5f27a2893b3f09f9a48a95710ad
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / fastapi_zcore_framework-0.1.0rc2-py3-none-any.whl
| Download URL | fastapi_zcore_framework-0.1.0rc2-py3-none-any.whl |
|---|---|
| Size | 117.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cabe3d52a0a5c59ddc6f0aad6e11452de2b1cb91c8bfa49220daf8f8ac94a78f
|
|
BLAKE2b-256 checksum How to use checksums |
0209c4abb3fdd0572d28c8b311c6a857c16aea8c6edd6beec641f082ec0f294b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log