Post/Put huge volume of data to an api endpoint through ADF

Hrishikesh K M 0 Reputation points
2026-10-16T07:34:29.6466667+00:00

I have few output files in my unity catalog volumes/adls gen2. I want to push the data of these files as a body for api endpoint. However the data from my table is huge which goes upto 2 million rows, which is then converted to the below formatted json file:

dataload:[

{

"Metadata": {

            "FinishExtract": true,

            "Timestamp": "20261016.124853",

            "OperationType": "Full"

           }

   },

   {

          Data: {

                    "Rows": [

                                 {

                                         "Values":[

                                                     "a",

                                                     "b",... "c"..,d,e,f,g,h,i]},

                                 {

                                          "Values":[j,k,l,m,n,o,p,q,r]}}} and so on.

this is a sample, I have total of 9 fields. The API only accepts this format as a downstream. Now, I want to understand what would be the right approach to send it in batches. The API can have 20 request and 0.5 million rows per request. The only option for me is to use ADF due to data restrictions.

I tried/explored the below approaches:

  1. Lookup + web (works, but size limit)
  2. Copy activity (content type conflict as I have to pass application/json;charset=UTF-8. I tried multiple options but nothing worked)
  3. Dataflows - Due to complex json, it was not able to format.
  4. Azure batch jobs/Azure functions/logic apps - Access restrictions, but this approach can be used if there's a workaround to solve the issue.
  5. Databricks job/notebooks - Access restricted, but this approach can be used if nothing else works.
  6. Databricks job + Web activity+ web activity - size limit.

I need my first request to go as a post request followed by put request. I can control the size and volumes my json files being generated. However, I can restrict the total volumes. I am looking for a scalable design.

Appreciate the help in advance!

Thank you.

Azure Data Factory
Azure Data Factory

An Azure service for ingesting, preparing, and transforming data at scale.

0 comments No comments

2 answers

Sort by: Oldest
  1. Rukshan edirisinghe 2,365 Reputation points
    2026-10-23T03:55:39.4833333+00:00

    Hi @Hrishikesh K M

    The catch here is the wrapper. ADF's REST sink sends data as a plain JSON array of records ([ {..}, {..} ]). It can reshape each record with mapping, but it can't add your outer dataload / Metadata / Data.Rows envelope. So the Copy activity alone won't produce the format your API needs.

    Since the data already sits in Unity Catalog / ADLS, I'd build the batches where the data is and let ADF orchestrate:

    1. In a Databricks notebook, read the table and split it into chunks of 500,000 rows or fewer (for example by row number ranges).
    2. For each chunk, build the exact body your API expects (Metadata block plus Data.Rows with the Values arrays) and POST it with requests. Use gzip if the API accepts it, since 500k rows is a large payload.
    3. Send the chunks one after another, with a short delay, and log the response for each batch so a failed batch can be re-sent alone.
    4. In ADF, call that notebook with a Databricks Notebook activity, passing the table name and batch size as parameters.

    With 2 million rows that's only 4 requests, well within the 20-request limit.

    Does the API expect the Metadata block in every request, or only in the first one?

    If this approach works for your load, please consider accepting it as the answer. If the API rejects the batched bodies, let me know and I'll be happy to keep helping.

    Reference:

    Was this answer helpful?

    0 comments No comments

  2. Silvio Lorenzo Torre 165 Reputation points
    2026-11-07T11:18:33.69+00:00

    Well, you are trying to send up to two million rows from ADLS Gen2 or Unity Catalog to an API that accepts no more than 500,000 rows per request, permits up to 20 requests, requires the first request to use POST and the following requests to use PUT, expects a specific JSON envelope containing metadata and nested rows and must be called from an ADF-controlled process.

    ADF Copy Activity with a REST sink is the scalable ADF-native option for batching. It supports POST, PUT and PATCH, and writeBatchSize controls the number of records sent in each request. So we made distinction is between batching records and constructing an arbitrary HTTP body when the REST sink serializes each batch as a top-level JSON array:

    [
      { "field1": "a", "field2": "b" },
      { "field1": "j", "field2": "k" }
    ]
    

    Schema mapping can change the fields inside each record, but it does not turn natively the REST sink into a raw-file pass-through client. We must first confirm whether the downstream API can accept this array format instead of requiring the exact dataload envelope shown in the question and if the API can accept the REST sink format, I suggest you to implement the pipeline as in the following steps:

    1. Partition the source into deterministic batch files. Each file must stay below both the API's row limit and its byte-size limit. Treat 500,000 rows as a ceiling, not necessarily the initial production batch size.
    2. Keep a small manifest containing sequence number, file path, row count and a stable batch ID.
    3. Process the first file with a Copy Activity whose REST sink uses requestMethod: POST.
    4. After that activity succeeds, process the remaining files with a second Copy Activity configured with requestMethod: PUT.
    5. Put the PUT activity inside a sequential ForEach (isSequential: true) if the API requires ordered delivery.
    6. Set writeBatchSize so that one source file produces one API request. Start with a smaller tested value, for example 10,000 or 25,000 rows, and increase it only after measuring payload size and API processing time.
    7. Add a stable batch/correlation identifier and make the PUT operation idempotent if possible. Otherwise an ADF retry after an uncertain response could create duplicate processing.
    8. Record the batch ID and API acknowledgement before advancing the manifest checkpoint. Caveat: do not use Lookup to materialize the two million rows before Web Activity. Lookup returns at most 5,000 rows and 4 MB, so that design fails before it becomes a scalable transfer mechanism.

    Regarding the Content-Type error: avoid defining Content-Type in more than one place. First test the REST sink without overriding it and inspect the actual request received by the API. If the API accepts only the literal value application/json;charset=UTF-8, while the connector sends application/json, this is an API-contract compatibility issue rather than a batching issue.

    If the exact nested dataload document is mandatory and the API cannot accept the REST sink's JSON array, I would not try to assemble a 500,000-row request with Lookup, variables or Web Activity. In that case there is no reliable ADF-only streaming solution for this contract. The scalable alternatives are:

    • modify the API to accept the REST sink batch format;
    • let the API accept a secure ADLS URL or manifest and read the file itself; or
    • have ADF orchestrate an approved Function, Databricks job or other controlled component that streams each prepared file as the raw request body. In larger enviroments prefer this one for better observability ;-)

    Because your environment restricts those compute options, the clean outcome may be a carefully scoped security approval for that component or downstream API contract.

    Microsoft documentation:

    I hope this is helpful. So please upvote the answer if the information helped you.

    And please note: This answer was partially prepared and translated into English with assistance from AI (ChatGPT/Mistral AI). I reviewed and validated the technical suggestions against previous experience and the Microsoft documentation linked above.

    Ciao

    Was this answer helpful?

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.