I have a Python FastAPI server application which naturally guides you towards the asynchronous paradigm.

For legacy reasons, I have to support two backends, one which is purely synchronous and one which is asynchronous. These backends roughly have the same functionality.

Are there any best-practices on how you could build up the package and module structure of your project? I can see two extreme cases:

  1. You split at the top-level with two packages sync and async and put the appropriate code in the corresponding package.
  2. On the module level, there are two functions doing the same, one is async, the other is sync.

Of course, between these extremes, there is a whole continuum of intermediate solutions.

What is your advice?

  • 2
    This sounds like if you have a need for function A() there will be a syncA() and a asyncA() each in their own package or module. I'm not sure why you think every function will need to exist in both forms. Seems to ensure that you'll be doing extra work. Feb 22 at 17:01
  • 2
    In many cases you can turn a blocking function into a background task with await asyncio.to_thread(function, args). That helps bridging between the blocking and async worlds. If at some point functionality is only accessed from async code, you can rewrite it as an async version. I'd rather not duplicate functionality if possible.
    – amon
    Feb 22 at 17:11


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.