Create your own
Lesson illustration

System Architecture: React, FastAPI, PostgreSQL/pgvector, File Storage, and Model Providers

Good to see you again. In the previous lesson, you defined the capstone’s core product contract: a customer asks a support question, the platform either produces a cited answer from organization-approved knowledge or escalates the case to a human agent. You also made organization isolation, customer-requested handoff, and evidence-based answers explicit requirements.

Now you will turn that workflow into a system architecture diagram. By the end of this lesson, you will have a C4-style container diagram that connects the React client, FastAPI service, PostgreSQL with pgvector, file storage, and replaceable model providers—and that you can later use in a portfolio architecture document or interview.


Choose the right architectural zoom level

For this stage, you do not need a diagram of Python modules, React components, tables, prompts, or deployment regions. You need a container diagram: a high-level view of the independently runnable parts of the application, what each part owns, and how they communicate.

In C4 terminology, a container is not necessarily a Docker container. It is a deployable or separately running application or data store, such as a React single-page application, an API service, a database, or object storage. A container diagram is the right level for making design choices visible without burying the reader in implementation detail.

What is the C4 Model? A Comprehensive Guide to Visualizing Software Architecture

Read the C4 Model guide from Visual Paradigm to establish what a container diagram communicates and how to label relationships clearly.

Read Section 2.2, “Level 2: Container Diagram,” in full. Focus on container relationships: each box needs a clear responsibility and technology label. Then read Section 3.2, “Relationships and Interactions,” especially the relationship-label guidance. Apply its advice by naming the protocol and purpose of each connection rather than writing vague labels such as “connects to.”

A useful test is this: a new engineer should be able to look at the diagram and answer all of the following.

  • Where does the customer interact with the product?
  • Which service enforces product rules and orchestrates AI work?
  • Where do source files live?
  • Where do conversations, tickets, and vector embeddings live?
  • Which boundaries are external services?
  • Which systems receive sensitive data or require secrets?

The C4 example below is not an AI application, but it demonstrates the intended level of abstraction: UI, backend, database, and external systems are separate containers with labeled relationships.

A C4 Level 2 container diagram separates a browser UI, backend application, database, file-oriented statement store, users, and external services. Each relationship names a purpose and protocol rather than merely showing that two boxes are related.

The architecture should reflect responsibility boundaries

Your capstone will have five essential technical boundaries.

Container or external systemTechnology directionPrimary responsibilityIt should not own
React clientReact + TypeScriptCustomer chat, knowledge-source upload UI, citation display, agent inbox, recoverable UI statesDatabase access, model API keys, authorization decisions
FastAPI servicePython + FastAPIHTTP API, validation, organization scoping, workflow rules, RAG orchestration, persistence coordinationLong-term storage of browser state or direct presentation logic
PostgreSQL + pgvectorPostgreSQL with the pgvector extensionRelational records and searchable chunk embeddingsOriginal PDF or document bytes as the primary file store
Object file storageLocal filesystem in development or S3-compatible object storageOriginal uploaded files and possibly extracted artifactsConversations, tickets, or vector similarity queries
Model provider(s)Hosted API or local model serviceEmbedding generation and text generationProduct policy, organization authorization, source-of-truth records

The important distinction is between data that must be queried transactionally and data that is a stored object.

PostgreSQL is the system of record for structured application data:

  • organizations;
  • knowledge-source metadata and ingestion status;
  • document chunks and their source locations;
  • embedding vectors stored through pgvector;
  • conversations, messages, tickets, citations, and feedback.

Object storage holds the original bytes of a source file, such as a PDF, Markdown file, or HTML export. The database stores an object key, content type, size, checksum, and ingestion state that refer to that file. It should not need to hold an entire PDF inside a large text column merely because the application can technically do so.

Likewise, pgvector is not a separate vector database in this design. It is an extension inside PostgreSQL that lets the database store and compare embedding vectors alongside ordinary relational data. This keeps source metadata, organization filters, ingestion state, and vector search close together.

The following short video gives a practical overview of this division of work in a React, FastAPI, and PostgreSQL RAG application. Its example uses a particular model provider, but the architecture pattern is provider-independent.

Python AI System Design: FastAPI, RAG & MCPs

Watch “Python AI System Design: FastAPI, RAG & MCPs” by sayed.developer for a concrete view of a document-chat product and the main connections between its UI, API, database, and models.

Watch the product overview to see document upload, chat, and citations as user-facing capabilities. Then watch the API boundary, focusing on why the React application sends requests to the backend rather than accessing internal services itself. Finish with PostgreSQL and vectors to connect chunk embeddings with retrieval. Treat the “vector database” language as an architectural role: in your capstone, PostgreSQL plus pgvector fulfills that role.


Draw the capstone container diagram

The diagram below is the baseline architecture for the product you scoped. It is intentionally small: it contains only the containers required to support the primary workflow. There is no web-search integration because web search is outside the first product slice, and there is no message queue yet because the project has not demonstrated a workload that requires one.

This is a static diagram. Its lines state structural dependencies and the kind of communication allowed; they are not a chronological account of one request. The next section supplies that operational interpretation.

The image below shows another AI customer-support sketch. It is useful for noticing the separation between frontend, backend, agent orchestration, and a pgvector-capable database. For your capstone, however, make file storage explicit and avoid drawing web search because it is deliberately out of scope.

An example AI customer-support architecture in which a React frontend communicates with a FastAPI backend, the backend coordinates AI-agent functions, and PostgreSQL with pgvector stores relational data and embeddings. The capstone architecture above makes object file storage and external model-provider boundaries explicit.

Read the diagram from the outside in

Customers and support agents both use the React client, but they see different capabilities. A customer submits support questions and views cited answers. A support agent sees escalated conversations, their reasons, and the ability to record a resolution. These are roles in the product, not separate backend services.

The React client calls only the FastAPI service. It must never connect directly to PostgreSQL, object storage credentials, or a model provider with a secret API key. A browser is an untrusted environment: users can inspect its network calls and compiled JavaScript.

The FastAPI service is the application boundary. It receives requests, validates them, establishes organization context, enforces deterministic workflow rules, and coordinates access to all internal and external dependencies. For example, it decides that an explicit request for a human must create an escalation rather than asking a model to decide whether the request is important enough.

The database holds the product’s durable state. A support answer may be generated by a model, but the conversation, its citations, its organization, and the resulting ticket must be recorded in PostgreSQL. The same applies to knowledge sources and their ingestion state.

The model provider is external and replaceable. You will later create an interface so that a free-tier hosted provider can be swapped for another hosted provider or a local model service without rewriting every route. For now, the architecture makes the key rule clear: only FastAPI talks to the provider.


Connect the diagram to the two core workflows

A diagram becomes useful when it can explain observable product behavior. The architecture supports two related paths: knowledge-source ingestion and customer support.

Knowledge-source ingestion

When an organization uploads a support document, the React client sends the file to FastAPI as a multipart HTTP request. FastAPI validates the file, writes the original bytes to object storage, and creates a knowledge-source record in PostgreSQL.

During ingestion, the FastAPI application retrieves the stored file, extracts and normalizes its text, divides it into chunks, and requests embeddings from the model provider. PostgreSQL stores each chunk, its source and position metadata, and the resulting embedding vector. The source record’s ingestion state tells the UI whether it is pending, processing, ready, or failed.

At this stage, do not assume that a separate worker, queue, or serverless function already exists. The diagram says FastAPI owns ingestion orchestration. If document volume or processing time later justifies an independently deployed worker, that worker should become a new container and be added to the diagram then.

Customer question and cited answer

When a customer sends a chat message, the React client calls FastAPI. The API records the incoming message and identifies the organization that owns the conversation.

FastAPI obtains an embedding for the customer’s question through the embedding-model capability of the provider. It uses pgvector to retrieve relevant chunks while filtering by organization and eligible source metadata. The API then sends the customer’s question and selected evidence to the text-generation capability of the provider.

Finally, FastAPI persists the generated message and citations, or creates an escalation ticket when evidence is insufficient or a human was requested. The React client receives an answer with citations or an actionable handoff state. In a later lesson, this response will be streamed incrementally to the browser; for now, a normal HTTP response is enough for the architecture.

Why there are usually two model operations

“Call the LLM” is too imprecise for an architecture explanation. RAG applications commonly have two different model operations:

Model capabilityInputOutputUsed for
Embedding modelA text chunk or customer questionA fixed-length numeric vectorIndexing source chunks and retrieving relevant chunks
Text-generation modelSystem rules, question, conversation context, retrieved evidenceNatural-language response, ideally structured dataProducing a grounded customer-facing answer or a support summary

A provider may offer both models, or you may use different providers. The diagram groups them as “Model provider(s)” because the crucial architectural boundary is the same: FastAPI calls the model service over an authenticated API, and the client does not.


Add the rules that make this a support system rather than a generic chatbot

The most valuable architectural decisions are not framework names. They are constraints that preserve the product promise from the previous lesson.

Organization scoping is an architectural invariant

Every relevant record in PostgreSQL belongs to an organization, directly or through a parent record. Every retrieval query must filter by organization before results can become model context.

This means a retrieval operation is not merely “find the nearest vectors.” It is “find the nearest eligible vectors for this organization.” Otherwise, the application could return another organization’s private support documentation as a citation.

At the architecture level, document this rule alongside your diagram:

FastAPI derives organization context for each request and applies it to all reads and writes. The React client may provide identifiers, but it is not the authority that decides cross-organization access.

A full authentication and authorization mechanism comes later in the course. You do not need to choose it today, but you should not draw an architecture that implies organization isolation will be added as an afterthought.

File storage is not automatically trusted

Uploaded PDFs and HTML files are user-controlled input. Storing them separately does not make them safe. FastAPI must validate file type, filename, and size before storing or processing them; later, the ingestion pipeline will also treat their content as untrusted text rather than instructions for the system.

Models are useful services, not policy owners

The system can ask a model to generate an answer from retrieved evidence. It should not ask the model to decide whether it may bypass a customer’s request for a human agent. Workflow requirements such as customer_requested_human and insufficient_evidence belong in deterministic application logic within FastAPI.


Create your architecture artifact

Now create your own draft container diagram in a diagram editor, Markdown document, or notebook. Redraw the baseline diagram rather than treating it as something to paste without understanding. Your version should use the names you expect to keep in the project and should fit on one page.

Use this checklist while drawing.

Diagram requirementWhat to show
System boundaryA boundary named AI Customer Support Platform around React, FastAPI, PostgreSQL/pgvector, and file storage
PeopleCustomer and support agent using the React client
React containerReact + TypeScript; chat, upload, citations, agent inbox
FastAPI containerPython + FastAPI; API boundary, workflow rules, orchestration
Database containerPostgreSQL + pgvector; relational application data, chunks, embeddings
File-storage containerOriginal uploaded documents, distinct from database records
External model systemOne or more providers for embedding and text generation
Relationship labelsProtocol and purpose, such as JSON/HTTPS for API calls and SQL for database access
No forbidden shortcutsNo direct React-to-database, React-to-storage, or React-to-model-provider connection
Scope boundaryNo web search, autonomous account actions, queue, or agent framework unless you can explain why the first workflow needs it

Add a short legend or set of notes beneath the diagram:

Architecture notes

1. PostgreSQL is the system of record for organization-scoped application data.
2. pgvector stores embeddings alongside chunk metadata for semantic retrieval.
3. Object storage holds original knowledge-source files; PostgreSQL stores their metadata.
4. FastAPI is the sole service allowed to access databases, object storage, and model providers.
5. Model providers are replaceable external dependencies.
6. A customer-requested human handoff and insufficient-evidence path are enforced by application rules.

This is an intentionally provider-neutral design. In local development, file storage might be a local mounted directory and PostgreSQL might run through Docker Compose. In deployment, they may become managed services. The logical responsibilities and boundaries should remain stable even when the hosting choice changes.


Key takeaways

A container diagram is the correct architecture artifact for this point in the capstone: it names the main deployable systems, their responsibilities, their boundaries, and their communication paths without pretending that internal implementation is already decided.

Your baseline system has five essential technical parts:

  • a React client for customer and agent experiences;
  • a FastAPI service that enforces workflow rules and coordinates dependencies;
  • PostgreSQL with pgvector for durable relational records and embedding search;
  • object storage for original knowledge-base files;
  • external, replaceable providers for embeddings and text generation.

Most importantly, the browser communicates only with FastAPI. FastAPI owns organization scoping, policy enforcement, and access to storage, databases, and model providers.

Next, you will compare free-tier services for these boundaries, considering quotas, storage limits, and fallback options before committing to specific providers.

Can't find a good explanation? Sign up and we'll make it for you

Sign up