Ensure that:
- You have thoroughly tested your dApp. Your tests should be based on security properties you want to maintain (who should/shouldn't be able to do X? under what conditions?). Write these properties down and review them as well.
- There are no private keys in the bundles
- Your private keys are stored securely (e.g. not served by the webserver)
- If you have private keys that are used specifically to control/shut down the system in case of a disaster, you are not storing them on the same server as the app.
- Blockfrost keys are not exposed to the user. If you run with Blockfrost, you have to set up a reverse proxy that attaches the project ID header.
Most likely, you will need a custom query layer to scale your dApp. Kupo is not very performant when it comes to handling a lot of queries on mainnet if it is configured to index the whole blockchain: it has a slightly different purpose.
The best approach would be to maintain your dApp state by folding incoming transactions (while handling rollbacks). Consider using Ogmios chain-sync API.
Here's how to plug your own query layer as a "provider" into CTL.
Use multiple backend instances if you have a lot of users, but avoid switching between different instances for a single user: CTL mildly relies on consistency of the state.
How many instances to run? Compute the number based on the response times of your query layer and expected number of users.
Set up monitoring and alerts for your backend services.
Ensure that you actively check the following:
- Disk space
- RAM usage
- Rate of failed requests to the query layer backend (e.g. kupo returns 503 when overloaded)
- Average response time
- Usage limits for Blockfrost