Basic Smart Contracts Limitations To Be Aware Of
Smart contracts are discrete computer program units, which are deployed inside blockchain network nodes. Once they are ready for deployment, usually the one-way hash value of the code is calculated and digitally signed. The one-way hash value, with its digital signature and the code itself, is then replicated out to the network of participating blockchain nodes. As part of the deployment process, each node verifies the one-way hash's digital signature, before it installs code locally. The node then waits for the smart contract ‘invocations’.
Since the smart contract code integrity is protected by its one-way hash value, which is digitally signed by the creator, it can't be changed once it has been deployed. The smart contract code is therefore immutable. It is somewhat similar, in nature, to the tamper resistant code deployed inside the smart card chip. Effectively, once it is deployed, the smart contract code becomes itself part of the immutable blockchain state, together with all of the historical transaction records and internal data structures maintained by the smart contract.
When invoked, smart contract code is executed on every mining and validating blockchain node that it has been installed on. Those nodes try to reach the consensus on the final outcome of their individual smart contract code executions. Once the consensus is reached, the blockchain network protocol ensures that the new updated state of the smart contract internal data is reliably and efficiently replicated to each node. Internal data structure is also immutable, meaning that nothing except the smart contract code itself can add to its content.
What You Shouldn't Do
The fact that blockchain nodes all execute the same smart contract code in parallel and fully independently, means that the smart contract code must be very deterministic in its nature, in order to be fully predictable, robust and reliable. That further means that the smart contract code invocation must produce the identical outcome in every node where it is executed.
That means that smart contracts designers should avoid relying on calls to external web services, APIs or external databases. If, for example, the smart contract needs to make internal decisions or update its internal state based on that API call response, can it be guaranteed that every instance of the smart contract would receive the exactly same response from the external component? Such design highly increases chances of multiple independent executions of the same smart contract code achieving very different results, causing chaos, all due to the inability of the participating blockchain nodes to reach final consensus.
That design can also lead to the situation where the external API gets called by the same smart contract instance running on every participating blockchain node. This, depending on number of participating nodes, can easily deteriorate into an unintentional 'DDoS-like attack' on the poor API, even if the API design is sophisticated enough to detect and properly deal with hundreds of duplicate calls. It would most likely and unnecessarily waste computer resources and potentially make the service unusable.
Although there could be some (more or less elegant) workarounds to the smart contract design limitations mentioned above, in my opinion, smart contracts can and should be used mainly for decentralized management of updates to its internal data state only. That state can then reliably be replicated to every blockchain node through consensus.
In other words, despite claims of their Turing completeness, current generation of smart contract platforms and languages can offer marginally more flexibility than plain vanilla public Bitcoin blockchain; mainly for more flexible implementations of decentralized digital asset transfers. Anything more sophisticated, may require interaction with indeterministic external environment and services, which would likely impose unmanageable testing complexity that is inherent in any highly distributed and decentralized system architecture.
It could and would easily turn into a nightmare testing and support scenario.