Skip to Content
Author's profile photo Thorsten Franz

Calling Function Modules in Parallel Universes

When you call a function module in a remote destination, a new internal mode and within it, an internal session is created in the remote system. So much is obvious.

But few people know how powerful (but also how dangerous) it can be to call an RFC-enabled function module of the local system with CALL FUNCTION … DESTINATION. (Either you can look up the destinatination of the local system via the logical system ID stored in table T000 or you spare yourself the trouble and just use destination ‘NONE’).

When using destination ‘NONE’, the function module will be executed in a new internal session under the same user id, which means:

  • The new internal session will contain new instances of every main program that is called inside it.
  • The state of the global memory of any function group, static attributes of global classes, and memories of main programs accessed through external performs are initialized “in a parallel universe” with respect to the caller’s internal mode.
  • This concerns for example the memory of the Business Application Log (BAL) and the memories of function groups that bundle data for updates IN UPDATE TASK and make them transparently available to callers according to the BAPI programming paradigm.
  • Locks are not inherited. Requests for a lock for a key that is already locked by the calling internal session will fail.
  • Commits and Rollbacks (both at database and LUW level) from the called function module’s internal mode have no effect on the caller’s internal mode and vice versa (except of course through the contents of the database).

The last effect is actually quite useful if you know exactly what you’re doing. It allows you to open an independent transaction or Logical Unit of Work that is isolated from the rest of your system state. I.e. it can be quite beneficial to call destination ‘NONE’ and create a new “parallel universe” where the static attributes of every global class are initial, and that won’t be affected by your COMMIT WORKs or affect you with its own COMMIT WORKs (or ROLLBACK WORKs, respectively).


  • You want to create a log entry in update task for a ROLLBACK WORK (or using OpenSQL for a database rollback) and you want to protect this from the effect of the very rollback it is documenting.
  • You want to start an error workflow IN UPDATE TASK and a ROLLBACK WORK in your internal mode should not roll back the function module registration.
  • You want to call a function module that you know or suspect causes commits or rollbacks which would mess up your own transaction handling (say, because you are working with OO transactions of the ABAP Object Services).
  • You want to create a sub-transaction like behaviour – say you want to call a BAPI that creates a business partner and you want to be able to roll it back later, but you don’t want the rollback to affect your main process or, and this is really fun, another business partner you’re also creating.

I like to think of the pseudo-remote internal session as a new bubble which is perfectly isolated from the bubble of the calling process.

Here are a few useful facts for working with bubbles:

  • The second bubble lives as long as the first one does.
  • You can call the second bubble repeatedly from within the first bubble.
  • Subsequent calls to the same destination but different function modules will be executed in the same bubble.
  • If you change the state of the global memory of a function group through CALL FUNCTION … DESTINATION … it will still be this way when you call this or a different function module in the same destination later. Try it out with a pair of RFC-enabled function modules Z_RFC_SET and Z_RFC_GET that operate on the same variable declared in the TOP-Include of the function group.
  • It is even possible to call back from the second bubble to the first bubble (also repeatedly) using CALL FUNCTION … DESTINATION ‘BACK’.
  • Other means of creating new bubbles include SUBMIT … AND RETURN and CALL TRANSACTION, but it’s more difficult to communicate with these bubbles and they burst as soon as the called programs have finished execution.
  • You can control the LUWs in the other bubble by calling BAPI_TRANSACTION_COMMIT and BAPI_TRANSACTION_ROLLBACK in destination ‘NONE’ or ‘BACK’.
  • You can write RFC-enabled function modules that wrap function modules DB_COMMIT and DB_ROLLBACK to control the database transactions in the other bubble.
  • Creating a new bubble is expensive in terms of system resources, and switching between bubbles is less expensive, but costs more than a local function call. The contents of the first internal session are moved out of the work process’ roll area, and the contents of the second internal session are loaded into it. When you return, the reverse happens.


If you don’t understand some of the above points, by all means forget this blog, or you might mess up your system and create errors that will be very hard to debug.


If you understand these things exactly, you can do some magic with them. RFCs offer so much fun – have you studied the asynchronous RFC for parallel processing? Anyway, enjoy.

Further Reading

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member
      Thorsten, will this eat up more system resources than a local call and thus slow down the program?
      Author's profile photo Thorsten Franz
      Thorsten Franz
      Blog Post Author
      Hi Vijay,
      absolutely correct. I wanted to mention this as one of the most important considerations already when Peter wondered if CALL FUNCTION ... DESTINATION should be the rule rather than the exception but forgot. If you don't mind, I'll insert this point into the blog later. 🙂
      Author's profile photo David Halitsky
      David Halitsky
      Glad to see our earlier discussion prompted you to "crank up the old motor" and actually post a full blog. 

      Great stuff!

      Author's profile photo Peter Inotai
      Peter Inotai
      Thomas: Thanks for writing this blog with summarizing up the whole idea from all aspects.
      David: Also thanks for you that you started this nice brain stroming. 🙂

      I would add, that if you want to play around with LUW, you have also the possibility to use asynchronous processing via statement "CALL FUNCTION func ...STARTING NEW TASK task name. "


      Author's profile photo Thorsten Franz
      Thorsten Franz
      Blog Post Author
      Thanks, David, for sparking the discussion. I'm one of those annoying people who think that asking the right question is often more important than giving the answer.
      I hope to see more of those interesting discussions.
      Author's profile photo Guillaume GARCIA
      Guillaume GARCIA
      Author's profile photo Thorsten Franz
      Thorsten Franz
      Blog Post Author
      Hi Guillaume,
      Thanks for pointing out the article. I think it gives an excellent overview. Readers should be aware that there are even more variants available:
      The aRFC has a distinctly different variant for parallel processing (using CALL FUNCTION ... DESTINATION IN GROUP ...) and the qRFC has a new relative, the bgRFC, which is even more powerful with regards to handling a number of different queues simultaneously.
      The fascinating thing about RFC is that it is very old, yet is constantly improved and extended. Just think of the new serialization and compression features.
      Best regards,
      Author's profile photo Thorsten Franz
      Thorsten Franz
      Blog Post Author
      Sorry, I posted too quickly. 🙂 The aRFC for parallel processing is explained in the article under the name "pRFC".
      Author's profile photo Brian Vanderwiel
      Brian Vanderwiel
      Excellent blog, thanks. 
      One other note to keep in mind...The act of calling the RFC (destination 'NONE') causes a COMMIT in the current session.  In other words, if you have database updates pending in the current session and you call the RFC, the DB updates will be committed.  As mentioned, any further updates in the current or new bubble can be controlled as necessary.
      Hopefully that makes sense.
      Author's profile photo Thorsten Franz
      Thorsten Franz
      Blog Post Author
      Hi Brian,
      Thanks for pointing this out. You're of course right. The COMMIT, it should be added, that is causes by the CALL FUNCTION ... DESTINATION is just a DB_COMMIT (database commit), not a COMMIT WORK (end of LUW), meaning the pending database updates are written, but form routines registered with PERFORM ... ON COMMIT and function modules registered with CALL FUNCTION ... IN UPDATE TASK are not executed.
      Ah, I love this stuff. 🙂
      Author's profile photo Alejandro Bindi
      Alejandro Bindi

      Hello Thorsten,

      Do you have any comments on calling an RFC f.m. STARTING NEW TASK from another f.m. running IN UPDATE TASK?

      I'm evaluating such alternative for running a parallel update from an update running BADI, without affecting the main (standard) transaction. It works fine according to all my tests (and I did a LOT), but still I'm not so sure about it, because if inside an UPDATE running function module, you call DB_COMMIT, you get a dump (POSTING_ILLEGAL_STATEMENT / Statement "COMMIT" is not allowed in this form.).

      So, by using STARTING NEW TASK (which essentially is an RFC call and hence should cause an implicit DB commit), shouldn't we get a dump also? I don't, but i'd like to be sure it stays that way...I see this solution is recommended a lot over the forums, but I'd like to know your comments on the subject.

      Many thanks and great blog!