Skip to main content

Connect ERP Integration (Oct 2026): 8 Seconds for NetSuite, Odoo, JDE

Cloud ArchitecturePalaniappan P13 min read

Quick summary: On October 27, 2026 a Connect flow still gives your Lambda 8 seconds to reach the ERP and return under 64 KB. NetSuite SOAP stops working with 2028.2. Odoo's external API needs a Custom plan. JD Edwards needs an orchestration you write.

Key Takeaways

  • On October 27, 2026 a Connect flow still gives your Lambda 8 seconds to reach the ERP and return under 64 KB
  • NetSuite SOAP stops working with 2028.2
  • Odoo's external API needs a Custom plan
  • NetSuite, Odoo and JD Edwards differ in everything else: protocol, authentication, concurrency and licence terms
  • Broader Connect work is on Amazon Connect consulting
Typographic data card, not a product screenshot. Headline: ERP lookups: 8 seconds. Table of limits: 8 s Lambda timeout in a flow, 64 KB response, 20 s for chained Lambdas, 2028.2 NetSuite SOAP removal, 3 months maximum Odoo API key life.
Table of Contents

On October 27, 2026, the rule for every ERP lookup in Amazon Connect is the same: the Invoke AWS Lambda function block waits at most 8 seconds (synchronous), and a Lambda response must be a flat map of strings under 64 KB. NetSuite, Odoo and JD Edwards differ in everything else: protocol, authentication, concurrency and licence terms. The shared design comes first, then each ERP, then a tested adapter that returns the same four fields from all three.

It is a design and a mocked test suite, plus one first-party run: on October 28, 2026 the unmodified Odoo adapter made 200 lookups against a local Odoo 19.0 container at p50 10 ms and p95 11 ms over localhost, with the shared-phone case returning AMBIGUOUS (method, raw results). We have not run it against a live NetSuite or JD Edwards tenant, or a hosted Odoo database, and FactualMinds has no published Connect-ERP engagement to cite. Broader Connect work is on Amazon Connect consulting.


ERP deep dives: setup steps, permissions and troubleshooting for each ERP are in Connect + NetSuite, Connect + Odoo and Connect + JD Edwards.

What agents and callers actually need from the ERP

Keep the first release to what changes a conversation:

  • Who is this? Match the caller to a customer record.
  • Is the account usable? Active, inactive, on hold.
  • What do they owe? Count of open invoices, and balance if finance allows it in the IVR.
  • Where is the order? Latest order reference and status.

Everything else (full invoice lines, credit memos, pricing) belongs on the agent screen, fetched on demand, not in the flow. This is the same split we use for commerce platforms in the AI customer support agent guide: small fast reads in automation, rich reads behind an agent’s click.

Architecture and capability labels

Caller -> Connect flow -> Invoke AWS Lambda (sync, 8 s max)
                              |-- Secrets Manager (credentials, cached at init)
                              |-- adapter: NetSuite | Odoo | JD Edwards
                              v
                        flat string map -> Set contact attributes -> branch on lookupStatus
PieceLabel
Invoke AWS Lambda block, contact attributes, Check contact attributesNative
Customer Profiles (profile objects, PutProfileObject)Native
AppFlow into Customer Profiles from Salesforce, Zendesk, Marketo, ServiceNow, S3Supported integration
NetSuite, Odoo, JD Edwards lookupsCustom engineering (the Lambda)
iPaaS connectors (Celigo, Workato, MuleSoft, and similar)Third-party, licensed separately; not evaluated here

Verify before choosing AppFlow

AppFlow is the first thing people reach for. We checked the supported-applications list on October 27, 2026. It names SAP OData, Microsoft Dynamics 365, QuickBooks Online, Oracle HCM and JDBC among dozens of entries. It does not name NetSuite, Odoo or JD Edwards. The JDBC connector exists, but pointing a contact-center sync at a production ERP database bypasses the vendor’s API, licence and governance model. We would not.

EventBridge is listed as an AppFlow destination. We found no AWS-documented native ERP-to-EventBridge publisher for these three systems, so any push model (NetSuite User Event script, Odoo automated action, JD Edwards orchestration with a notification) is custom code you own.

Live lookup versus cached summary

Live call in the flowCached summary in Customer Profiles
FreshnessSecondsAs old as the last sync
Failure modeEats part of the 8 s, then falls backServes stale data confidently
ERP loadOne burst per contactOne scheduled job
WhereIVR, chat bot, flow branchingAgent screen, pre-routing

Our recommendation: live for the IVR and bot path, cached for the agent screen, and never both pretending to be the same fact. The trade-off is two code paths. The reason is that the IVR path must decide in 8 seconds and tolerate a miss, while the agent path can afford a 10-minute-old balance if it displays the sync time.

A cache is custom: define a profile object type with PutProfileObjectType, then write summaries with PutProfileObject. Detail on shaping the agent view lives in the sibling post on custom agent UI and Customer Profiles.

The Connect Lambda contract

Verified in the AWS Lambda-in-flows guide:

  • Synchronous timeout: 8 seconds maximum. Failed invocations are retried up to 3 times within that window.
  • Total duration of a sequence of Lambda blocks: 20 seconds.
  • Response validation STRING_MAP: a flat object of string values, alphanumeric, dash and underscore only, under 64 KB of UTF-8.
  • Values saved with Set contact attributes appear in contact records. Values read directly as $.External.* do not.

The character rule matters for ERPs. A balance of $1,204.50 or an order status of Pending Fulfillment is not a legal value, even though a docs example elsewhere shows $1000. The adapter replaces anything outside [A-Za-z0-9_-] rather than testing how Connect reacts.

Authentication and secrets

  • Put credentials in AWS Secrets Manager, read them in the init phase, cache them for the container’s life.
  • One credential per ERP, one least-privileged ERP role: read-only on the customer, invoice and order records you map. No write scopes.
  • Never return a token, internal ID or free-text name to the flow unless the flow needs it. Anything in contact attributes is stored on the contact record.
  • Validate the caller’s number against E.164 before it reaches a query. The NetSuite adapter builds SuiteQL text, and the test suite includes an injection-shaped phone number.

NetSuite

The generic account-and-data side is on the existing NetSuite integration with AWS page. This section is only what the contact center changes.

Interface. Use SuiteTalk REST web services: the record API for single records, and SuiteQL (a SQL-like query via REST) when you need a join or filter. Use a SuiteScript RESTlet only where REST cannot do the job; Oracle says it supports that scenario but you do not get 100% parity with SOAP. The adapter posts to /services/rest/query/v1/suiteql with a Prefer: transient header and a limit query parameter. Those two details come from integration-vendor documentation, not an Oracle page we could open, so confirm them against your release.

SOAP status. Oracle’s SOAP removal FAQ gives the schedule:

ReleaseWhat Oracle says
2025.2Last planned SOAP endpoint
2026.1New integrations should use REST with OAuth 2.0
2027.1No new integrations with TBA or SOAP; existing ones keep working
2027.2Only the last endpoint supported; older ones disabled one per release
2028.2All SOAP endpoints disabled

A Connect integration started now should not touch SOAP at all.

Authentication. On the integration record, enable Client Credentials (Machine to Machine) Grant and the REST Web Services scope; Oracle notes this grant does not support public clients. Per Oracle, only new integrations must use OAuth 2.0 starting with 2027.1, and OAuth 2.0 is preferred over TBA now. The exact JWT assertion rules (signing algorithm, certificate lifetime, role restrictions) live on a separate Oracle page. We read the overview but not that page, so the adapter’s NS_JWT_ALG default of PS256 and its claims are unverified. Treat the token code as a starting sketch.

Concurrency. This is the NetSuite-specific failure risk. Oracle’s SuiteCloud Plus page says web services and RESTlet requests share one account limit, each SuiteCloud Plus license adds 10, the base limit depends on service tier, and enforcement is “lenient” so brief overages are possible. Base numbers per tier were not in the pages we read, and third-party sources conflict, so we give none. You can allocate part of the limit to a specific integration (Setup, Integration, Manage Integrations).

Design consequence: the adapter makes three SuiteQL calls per contact (find the customer, then an exact COUNT(*) of open invoices and the newest sales order in parallel), and one token request per container. Each call counts against the account’s concurrency limit, so the parallel pair can take two slots at once. Cap Lambda reserved concurrency for the function so a promotion-day call spike cannot take the whole account budget. Licensing cost for SuiteCloud Plus is not published; get a quote.

Role and permissions. Create a dedicated role with view-only on Customer, Invoice and Sales Order, assigned to the integration’s entity. Which exact permission names SuiteQL needs for each table is something we did not verify.

Phone matching. NetSuite phone fields are free text. Exact match on +14155550123 will miss (415) 555-0123. Match on a normalised custom field you maintain, or do not use phone as the key.

Odoo

Existing background: Amazon Bedrock and Odoo integration.

Interface and timeline. Odoo’s current documentation describes the External JSON-2 API: POST /json/2/<model>/<method>, with an Authorization: bearer <API key> header and an optional X-Odoo-Database header when one server hosts several databases. The older XML-RPC (/xmlrpc, /xmlrpc/2) and JSON-RPC (/jsonrpc) endpoints are deprecated. The Odoo 19 page states they are scheduled for removal in Odoo 22 (fall 2028) and Odoo Online 21.1 (winter 2027). A GitHub documentation commit appeared to give an earlier date, so the schedule has moved; check the page for your version. For a new build, use JSON-2.

Keys. Created under Preferences, Account Security, New API Key. A key needs a description and a duration of at most three months, and is shown once. Plan a rotation job. Programmatic key management exists through res.users.apikeys.generate(), limited by default to users with the Settings administration access right, with up to 10 keys per user.

Edition constraint. The same page says external API access is only available on Custom Odoo pricing plans, and not on One App Free or Standard. What that means for self-hosted Community, Enterprise on-premise or Odoo.sh was not on the page we read: unverified. Settle it with your Odoo contract before a project starts. A missing entitlement is a worse surprise than any latency.

Models. The adapter reads res.partner (customer, by phone), account.move (posted out_invoice moves with payment_state of not_paid or partial) and sale.order (latest by date_order). These are standard Odoo models and field names; we did not verify them against a running instance, and customised databases often differ. One search_count plus one search_read run in parallel after the partner lookup, so the path is three requests with two in flight at once.

Odoo user permissions. The API key acts as its user, so create a dedicated user whose access rights are read-only on those three models. Odoo’s docs describe access rights and record rules applying to API calls; confirm in a test database that your rules hide what you expect.

JD Edwards EnterpriseOne

Interface. AIS Server exposes REST services under https://<ais_server>:<port>/jderest/.... For this use case use an orchestration built in Orchestrator Studio: Oracle documents that a saved orchestration is published as a REST service at /jderest/orchestrator/<orchestrationname>, invoked by POST with inputs in the request body. The adapter expects an orchestration named in JDE_ORCHESTRATION that takes phone and outputs the four mapped fields. That orchestration is custom engineering: you design, secure and version it. Its input and output names in our sample are our convention, not an Oracle contract.

Version. AIS v2 services need Tools 9.2.1.2 or later (documented). A minimum Tools release specifically for Orchestrator was not stated on the pages we read; we saw a deployment note that the current Orchestrator Studio line requires the matching Tools release, so verify for your estate.

Authentication. Two documented routes. Send Authorization: Basic ... on each orchestration call (Oracle describes this as used for IoT devices calling orchestrations), which is stateless: credentials are supplied and a temporary session ends with each request. Or request an AIS token at /jderest/v2/tokenrequest (Basic auth plus jde-AIS-Auth-Environment, -Role and -Device headers) and pass it as jde-AIS-Auth. A token route saves repeated sign-on cost but adds state, device binding and an expiry you must handle. The sample uses Basic per call for simplicity. Oracle also documents a JWT bearer option with an external identity provider; it needs trusted-node and certificate configuration. Whether Basic auth is enabled on your AIS Server is an administrator setting; one source we read says it must be enabled in Server Manager.

Network and latency. AIS Servers are commonly on private networks. We did not find an Oracle statement either way, so check your estate. If it is private, the Lambda runs in a VPC with a route over Site-to-Site VPN or Direct Connect. Lambda in a VPC then needs an interface endpoint or NAT route to reach Secrets Manager. Every one of these hops spends the same 8 seconds. Measure from the Lambda subnet, not from a laptop.

Licensing. We did not verify what Oracle requires licence-wise for AIS or Orchestrator use by an external system. Do not assume it is included. Ask your Oracle account team in writing.


Data mapping

Field (flow attribute)NetSuiteOdooJD EdwardsProfile object (custom)
accountStatuscustomer.isInactiveres.partner.activeorchestration outputAccountStatus
openInvoiceCountcount of CustInvc with status Aaccount.move count, posted, unpaid or partialorchestration outputOpenInvoiceCount
lastOrderStatuslatest SalesOrd statussale.order.stateorchestration outputLastOrderStatus
lastOrderReftranIdsale.order.nameorchestration outputLastOrderRef
lookupStatusadapteradapteradapternot stored

The right column is a design you create with PutProfileObjectType. It is not a built-in schema. The flat map is what makes three different ERPs look the same to a flow: add a fifth field in one place and every adapter must provide it or return UNKNOWN.

Failure handling inside 8 seconds

The handler never throws. It aborts the ERP call at 5 seconds (AbortSignal.timeout, capped at 6 seconds whatever ERP_BUDGET_MS says) and returns lookupStatus=FALLBACK with a reason: TIMEOUT, HTTP_401, HTTP_503 and other HTTP codes, AMBIGUOUS, BAD_RESPONSE, BAD_INPUT or NOT_CONFIGURED. All data fields become UNKNOWN.

Three of those reasons exist to stop a wrong answer. AMBIGUOUS: NetSuite and Odoo are asked for two matching customers, and two means a shared number, so neither is read out. BAD_RESPONSE: a 200 response without the expected fields (a NetSuite error body, a broken JDE orchestration) is never reported as OK or NOT_FOUND. NOT_CONFIGURED: missing credentials or URLs are reported as such, not as a customer who does not exist. The Odoo adapter also sends active_test: false, because Odoo filters archived partners out by default and INACTIVE could otherwise never be reported. The flow checks lookupStatus and sends the caller to a human or a generic path.

Why not rely on Connect’s Error branch? Because Connect retries a failed invoke up to 3 times inside the same 8 seconds, and an error branch tells you nothing about why. With a clean fallback you get a reason in the contact record and a branch you designed.

// handler.mjs (Node 24): abort the ERP call before Connect's 8 s ceiling, never throw.
try {
  const raw = await adapter.lookup({ phone, cfg, fetchFn, signal: AbortSignal.timeout(budget) });
  return toStringMap(raw);
} catch (e) {
  const timedOut = e?.name === 'TimeoutError' || e?.name === 'AbortError';
  return fallback(timedOut ? 'TIMEOUT' : (e?.code ?? 'ERP_ERROR'));
}

Where this breaks

What could break (modeled, not an incident) — Three sequential ERP calls that each take 2.8 seconds finish at 8.4 seconds, after Connect has already routed the contact to the Error branch. The Lambda keeps running and bills for it, and the caller hears the failure path. Our budget math: token request (cached after the first call), plus one SuiteQL call and then two in parallel, must fit well inside 5 seconds at your measured p95, or move that ERP to the cached pattern.

Two further breaks to expect: the phone key (free-text formats) returns NOT_FOUND for real customers, and the account-wide concurrency on NetSuite throttles under a spike.

Deployment, testing and validation

  1. Add the function to the instance (Flows, AWS Lambda) and grant the Connect principal invoke permission.
  2. Set the block to Synchronous, STRING_MAP, timeout 6 to 7 seconds so the handler’s 5-second abort fires first.
  3. Test each adapter against a sandbox ERP before production: NetSuite sandbox account, Odoo test database, JD Edwards non-production environment.
  4. Run node --test in the artifact. The 13 tests check output shape, fallback on timeout and on HTTP 503, query-injection rejection, the NetSuite token request (claims, and reuse on a warm call), inactive accounts in NetSuite and Odoo, ambiguous matches, error bodies returned with HTTP 200, missing config, and a log line that never contains the phone number.
  5. In the flow, use Connect’s test and simulation to confirm the attribute names you reference match the keys returned.
  6. Alarm on duration and on FALLBACK by reason. The handler never throws, so Lambda’s Errors metric stays at zero; the signal is the one JSON log line it writes per call (lookupStatus, fallbackReason, duration, never the phone), read through a CloudWatch metric filter.

Reproduce this — The adapters, README, sample event and test file are in /examples/architecture-blog-2026/connect-commerce-context/erp/. Run cd examples/architecture-blog-2026/connect-commerce-context/erp && node --test. Expected output: 13 passing tests. All HTTP is mocked; it has not been run against live ERPs. The handler is handler.mjs.

Costs (published only)

  • Lambda: the published free tier is 1 million requests and 400,000 GB-seconds a month. Beyond it you pay per request and per GB-second. See the Lambda pricing page for current rates.
  • Site-to-Site VPN: charged per connection-hour, plus data transfer out, per the VPN pricing page. Direct Connect has its own pricing.
  • Secrets Manager: per secret per month and per 10,000 API calls. Caching at init keeps the call count near the number of cold starts.
  • Not published: NetSuite SuiteCloud Plus, an Odoo Custom plan, Oracle JD Edwards licensing, and any third-party iPaaS. We list none of these because we cannot cite a price.

Recommendation

Build a thin Lambda per ERP behind one output contract, start with live reads for the IVR, and add a cached summary for the agent screen only when measured latency says so. The trade-off is custom code that you maintain across ERP releases. We prefer it to an iPaaS for a four-field lookup, because the iPaaS adds a licence, a hop and a second timeout inside the same 8 seconds. Choose an iPaaS when you already run one for finance and want its connectors, monitoring and retry policies, and verify its added latency first.

By ERP: NetSuite is the safest on tooling and the riskiest on shared concurrency. Odoo is the simplest API and the one with the plan question to settle first. JD Edwards has the lowest-level control and the most project work, because you build the orchestration and the network path.

What to do this week

  1. Measure p95 round-trip from the Lambda’s subnet to the ERP. If it exceeds 3 seconds, plan the cached pattern first.
  2. Confirm entitlement in writing: NetSuite integration role and concurrency allocation, Odoo plan, Oracle licensing for AIS and Orchestrator.
  3. Create a read-only ERP user or role for the integration, and store its credentials in Secrets Manager.
  4. Clone the artifact, replace the field mapping, and run node --test.
  5. Build the flow with a lookupStatus branch before any data branch.
  6. Add the FALLBACK metric-filter alarms (by reason) before you route live traffic.

What this post doesn’t cover

  • A live run against any of the three ERPs. The only tests are mocked.
  • NetSuite OAuth 2.0 client credentials details (JWT algorithm, certificate lifetime, role restrictions), per-tier concurrency numbers, and the Oracle page for SuiteQL limits.
  • Odoo licensing outside the documented Custom-plan rule, and any difference between Online, Odoo.sh and self-hosted for the API.
  • JD Edwards licensing, the minimum Tools release for Orchestrator, and token expiry values.
  • Writes back to the ERP (creating a case, updating an address). Read-only is a deliberate scope.
  • Third-party iPaaS evaluation, ERP-to-Connect event push, and the Shopify, BigCommerce and WooCommerce side. See Connect and Shopify and BigCommerce and WooCommerce.
  • Compliance. Running on AWS does not make customer or invoice handling compliant.

For an overview of how we approach the commerce side of Connect, see Amazon Connect for eCommerce.

Frequently asked questions

Can Amazon AppFlow load NetSuite, Odoo or JD Edwards data into Connect Customer Profiles?
Not as native connectors. On October 27, 2026 the AppFlow supported-applications list includes SAP OData, Microsoft Dynamics 365, QuickBooks Online, Oracle HCM and JDBC, but not NetSuite, Odoo or JD Edwards. The Customer Profiles API documents Salesforce, Zendesk, Marketo, ServiceNow and Amazon S3 as AppFlow sources. For these three ERPs you write a Lambda, or buy a third-party iPaaS connector.
How long can a Connect flow wait for an ERP lookup?
A synchronous Invoke AWS Lambda function block allows a maximum of 8 seconds. Errors are retried up to 3 times inside that window, then the flow takes the Error branch. A chain of Lambda functions is limited to 20 seconds in total. Asynchronous mode allows up to 60 seconds, but the contact does not wait.
When should we not call the ERP live from the flow?
Skip the live call when the ERP is slower than your budget at p95, when it sits behind a VPN you cannot make highly available, or when the account limit is shared with finance integrations. Then publish a small summary to Customer Profiles on a schedule and read the cache. Accept that the data can be stale and show the age.
What could go wrong with NetSuite concurrency?
Web services and RESTlet requests share one account concurrency limit, and each SuiteCloud Plus license adds 10. Oracle's page says the base depends on service tier but does not list it in the pages we read. A peak of simultaneous calls from the contact center can starve a finance integration. Use a per-integration allocation and cache on the Lambda side.
Is the Odoo external API available on every plan?
No. Odoo's documentation says access to data via the external API is only available on Custom pricing plans, and not on One App Free or Standard. Self-hosted and Odoo.sh licensing is not covered by the page we read, so treat it as unverified for your contract.
Which NetSuite authentication should a new Connect integration use?
OAuth 2.0 with the client credentials (machine to machine) grant. Oracle says new integrations built from 2026.1 should use REST web services with OAuth 2.0, and from 2027.1 new integrations cannot use token-based authentication. SOAP requires TBA, so SOAP is not a starting point.
Does using AWS make this integration compliant?
No. Customer and invoice data are personal data. You still own access scoping, retention, logging and the ERP vendor's terms under shared responsibility. Return the minimum fields to the flow, because values stored as contact attributes are included in contact records.
What breaks first on JD Edwards?
Latency and ownership. AIS is usually on a private network, so the Lambda needs a VPC route (Site-to-Site VPN or Direct Connect), and each hop spends part of the 8 seconds. The orchestration is a custom artifact someone must version and test across Tools releases.
Palaniappan P
Palaniappan P

AWS Cloud Architect & AI Expert

AWS-certified cloud architect and AI expert with deep expertise in cloud migrations, cost optimization, and generative AI on AWS.

AWS ArchitectureCloud MigrationGenAI on AWSCost OptimizationDevOps

Recommended Reading

Explore All Articles »