2

This is a conceptual question about whether my specific use-case warrants the use of an asynchronous API.

Language: Python 3.11 Framework: FastAPI (ASGI)

I believe I am confused about what an asynchronous API really means, differentiated from asynchronous processing (multi-threading, event-loops, futures).

I am under the impression that the strength of an asynchronous API is that it can handle multiple requests at once, leading to less request timeouts.

Because we wanted to avoid request timeouts, I was asked to make a certain API asynchronous. This API only had 1 job to do once a day, but the computations took around 1 hour to complete. By the time the computation was done, the service awaiting for our response would've timed out...

The understanding on our part was that the app will:

  1. Receive request
  2. Immediately respond with 202 Accepted (so that the request is not timedout)
  3. Process request after responding
  4. Send the result

Is this correct or an absolutely erroneous understanding of what/how asynchronous APIs operate?

In our use case does it even make sense to worry about asynchronicity?

10
  • 4
    That is... wild. The premise, the lacking implementation details, the assumptions we could say anything worthwhile without it... I am afraid you will not get any usable answers unless you give us a lot more details. What do you mean by "async API"? What language? What framework? Which language feature do you want to use to implement "async"?
    – nvoigt
    Commented Jan 15 at 15:28
  • Any server should be able to handle parallel requests even if your API was written as sync. Do you have a server for your API (for example a web server and a REST API) or is it something you wrote yourself?
    – nvoigt
    Commented Jan 15 at 15:29
  • 6
    There are two largely unrelated meaning for "asynchronous" in this context. (1) A non-blocking implementation, e.g. using multithreading, event loops, or async–await keywords. This lets your CPU continue working on another request while waiting for I/O like a database query. (2) An API design style where requests doesn't get a response immediately. In HTTP this is necessary for long-running tasks to prevent timeouts, and even has its own status code: 202 Accepted. The difficult part: how does the client know you're done?
    – amon
    Commented Jan 15 at 16:02
  • Before you get to deep into solving this with the web understand we solved this exact problem decades ago with email. At this time scale we call the work a batch process. Users should not be watching something spin for an hour. Web apps can simulate email. Look into long polling. It’s how we watch votes come in here. Commented Jan 15 at 17:17
  • 2
    If the 'thing' takes an hour, you probably want some way to monitor the progress, or at least be able to tell that it is actually working, and have not just silently failed or hanged.
    – JonasH
    Commented Jan 16 at 12:19

3 Answers 3

5

Think of this as two distinct responses. A response to the initial request and then a response to the result. The result response will not be on the initial request.

When ordering fast food, you have an interaction with a cashier and get a ticket with your order. At some point your order completes and you are notified and pick up your order. Two separate events. Also, you don't keep standing in the order line waiting and waiting (and potentially block other people from ordering).

Similar process here, first you are going to submit your "order" / request. Behind the scenes a message gets dropped in a queue (or similar) and then you will return the order ID of the request to caller. Another process will pick it up and process it.

At some point the process will error/succeed. At that point, the client will be notified. Notification could be email, text message, a message using web sockets, etc. One can also provide an API to check on status of past requests as well since you can use the original order Id.

Most likely the original request will be asynchronous, but short lived. Ideally, the submission process should only take at most a few seconds.

Your "API" may have 3 methods:

  • Post to Submit a Request
  • Get to Check Request Status (By Id)
  • Get to retrieve the result of request (By Id)

One can use polling or push method to get the result. A push would be more efficient.

3

If caller should be able to monitor status of the task and be able to find out whether final result (eg. completed or failed), you can:

  1. return response with status code 303 and Location header status code 303 and information about the task (when it was started, hyperlink to url in location header, how far along it is). You can alse return Retry-After header to indicate that user should wait a bit before trying the url.
  2. url in location would return 303 response leading back to itself if task is still running or to final result if it is completed.
3

I am under the impression that the strength of an asynchronous API is that it can handle multiple requests at once, leading to less request timeouts.

Not exactly. A synchronous API can also handle multiple requests. The main reason for implementing an async API is to avoid long response times. Super-long response times are generally problematic and in some environments they are limited. For example, the AWS API Gateway will fail any request that doesn't complete in less than 30 seconds.

You aren't entirely wrong, though. One of the big problems with long response times is that those requests hold server-side resources while they are waiting. If you have a lot of concurrent requests and they are all taking a long time to respond, you will, in general, need more server-side resources to handle that load than if you use an async design.

Another related reason to use async APIs is for uneven loads. If you get unpredictable bursts of activity, it can be very costly to ensure that you will have enough server-side capacity to handle them at any given moment. So even if, under normal load, you respond quickly, you could end up swamped during the heavy period. An async design allows you to buffer requests and (eventually) process them successfully when volume exceeds throughput for some limited period and then returns to normal.

An hour is a really long time for an HTTP call to take. There are many things that can happen in such a timespan. The client could crash or otherwise disconnect, for example. Making this async is a reasonable thing to do. I would add a GET status URL as mentioned in user470365's answer. This is a widely-used approach. You might also want to consider the redirect response as well depending on your situation. It's not strictly necessary, though. You can return a URI in the 202 response content, as an alternative.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.