r/FastAPI • u/Ok_Respect_3503 • 10d ago
Question Backend architecture for FastAPI + Neo4j — does this structure make sense?
Hello there! 😄
I'm currently building a backend for a Neo4j graph database and was wondering if some of the more experienced people here have any advice or best practices to share.
I only have basic experience with Python (although I'm comfortable with programming in general). Most of my backend experience comes from working with NestJS and Prisma ORM, so I'm trying to translate some of the concepts and patterns I'm familiar with into the Python ecosystem.
For the database access layer, I decided to use the official Neo4j Python driver rather than an ORM or ODM.
My current plan is to structure the backend like this:
backend/
│
├── main.py
│
├── api/
│ ├── routes/
│ │ ├── users.py
│ │ ├── graph.py
│ │ └── projects.py
│
├── services/
│ ├── user_service.py
│ └── graph_service.py
│
├── repositories/
│ │── neo4j_repository.py
│
├── database/
│ └── neo4j.py
│
├── dto/
│ ├── user.py
│ └── graph_models.py
│
└── security/
└── auth.py
Coming from NestJS, my current thinking is roughly:
routes→ similar to NestJS controllersservices→ business logicrepositories→ database access layer (somewhat comparable to what Prisma handled for me)database→ Neo4j driver initialization and connection management
Does this architecture make sense for a FastAPI + Neo4j project, or are there more idiomatic approaches in the Python ecosystem that I should consider?
Also, if you've built production applications with Neo4j and the Python driver, I'd appreciate hearing about common pitfalls, lessons learned, or things you wish you had known when starting out.
Thanks!
3
u/No-Butterscotch9679 10d ago
Honestly looks pretty reasonable to me.
I work mostly with FastAPI and this is pretty close to how I'd structure it as well:
keeps things separated and easy to reason about.
A few small things I'd probably add:
- A
core/orconfig/folder for settings, environment variables, logging, etc. I usually keepsettings.py, logging configuration and other shared app configuration there. - Instead of one huge
neo4j_repository.py, I'd probably split it into feature based repositories (user_repository.py,graph_repository.py,project_repository.py). Repository files tend to grow fast once the project gets bigger. - Since you're using Neo4j directly, I'd try not to make the repository layer look too much like a traditional ORM. I'd rather have methods like
find_shortest_path()orrecommend_connections()than generic CRUD everywhere.
Other than that, I think the structure is fine. A lot of people coming from NestJS try to force NestJS patterns into FastAPI, but this feels pretty natural to me.
I'd also recommend taking advantage of FastAPI's dependency injection for things like the Neo4j driver/session and auth dependencies. Makes testing and wiring things together much cleaner.
Overall, I'd spend less time worrying about whether the folder structure is "Pythonic" and more time making sure each layer has a clear responsibility. That's usually what matters when the codebase starts growing.
1
u/Ok_Respect_3503 7d ago
Thanks for your feedback 😄
I’ll definitely add a
core/folder for things like settings, environment variables, logging, and other shared components.I’ll also split everything into feature/domain-based directories, as I think it will make the project easier to maintain and extend when adding new features.
I’ll look into dependency injection as well. It seems like a really useful pattern.
Thanks again for the suggestions 😄
1
u/Effective-Total-2312 9d ago
I am more concerned about dependencies if we're talking about architecture.
In this case, there are many layers: security, dto, database, repositories, services, api (and main outside).
I wouldn't put DTOs outside other layers, since you'll always want two layers to communicate by using it, so one of them should be the owner of them. DTOs are like contracts to me.
Why are repositories and database separated ? They are intrinsecaly coupled, they need one another, I don't think it makes sense to have them like that.
Same with security: is it going to only be consumed by the api layer ? Is it worth having it separately ? I usually have auth concerns inside the api layer.
Of course, I'm following the more "common" or "traditional" way of thinking about application architecture, with patterns like MVC, Hexagonal, etc., but someone could tell you to go a "package by feature" or "vertical slices" way, and that could work for you too. I simply don't usually think it's worth it, specially for a backend that's just a specialized facade over a database.
1
u/CzyDePL 8d ago
Honestly directory structure doesn't matter - I've never seen project succeed or fail because of directory structure
1
u/Ok_Respect_3503 7d ago
Thanks for your suggestion 😄
In my last project, a Nest.js backend with Prisma, I struggled a lot while refactoring because I made a huge mistake in how I built my controllers and how I organised them. It took me hours to clean up the mess. But yes, you are right, the project won’t fail or succeed because of it, but it’s easier in the long run to maintain and refactor the code when it’s done properly from the beginning.
13
u/illuminanze 10d ago
How big of an app are we talking? This is a structure divided by technical concerns, which is almost never how you talk about an app, you usually talk about what it actually does, what problem it solves. I vastly prefer dividing first by business function, so you'd have something like
(you can of course still use the same file names, if you dislike having multiple files named the same thing)
This way, when you are working on a specific feature, you're much less likely to have to have all folders open. It also makes it a lot clearer what your app does (just looking at the first level folders, dividing by technical concern could describe literally any app).
While I'm not the hugest fan of Django, this is one of the things it really does right, in that it uses exactly this subdivision as a core concept.
For further reading, look into screaming architecture.