SlideShare a Scribd company logo
1 of 40
Lessons from developing anIphone App + Server backend Sujee Maniyam s@sujee.net http://sujee.net http://DiscountsForMe.net Sep 2009
Target Audience Iphone app developers Server backend developers for mobile apps Expert level: Beginner - Intermediate
My Background Developer (enterprise, web) Java / Php / Ruby First iphone/mobile app
App: DiscountsForMe Shows member benefits Based on location V2.0 in app store Memberships: Public radio (KQED, WHYY) Bank of America card AAA, AARP More…
Architecture Server (DiscountsForMe.net) serves data Server is Rails app Iphone app talks to the server <Insert usual SERVER ---- INTERNET CLOUD ---- IPHONEpicture here>
Connectivity : Simple Start First cut : App made three server calls at startup ping() get_A() get_B() Simulator   Iphone over Wi-fi Iphone over 3G  LAG-TIME is a problem
Connectivity : Minimize Lag Time Noticeable lag time over 3G/Edge Reducing lag time Download in background Condense network calls (especially if the user is waiting for data) So Get_A() Get_B() get_A_and_B()
Iphone Connectivity BIG LESSON 1 :  Test on IPHONE (not just simulator) Test with WiFi OFF!  (3G can be slow to connect, EDGE even worse) You may need to reorganize the logic to improve response time (I had to) LESSON 2 Test in AirPlane Mode (all RADIOS off)(a frequent reason network apps are rejected )
Talking to Server : Format Two choices :   XML, JSON JSON smaller size than XML (50% less) Json  : use TouchJSON library http://code.google.com/p/touchcode/wiki/TouchJSON XML : NSXML(sdk)  / TouchXML / KissXMLhttp://www.71squared.co.uk/2009/05/processing-xml-on-the-iphone/ Rails makes it real easy to send Json/xml Some_obj.to_json Some_obj.to_xml
Keeping it small Trim objects No need to send all attributes Active records have extra attributes (created_at, updated_at ..etc) Example: my_response = {} my_response[:book_name] = book.name my_response[:book_description] = book.description my_response[:author_name] = book.author.name render(:json => my_response.to_json()) - Compress (zip) response
Agenda Connectivity Data format Secure Data transfer UDIDs, Keys, analytics Controlling app from server
Secure Data Transfer Plain HTTP is fine most of the time If you want to secure data Symmetric key encryption (shared ‘seckr3t’ key on Iphone app and server) Public-private key encryption (e.g. SSH) : private key on server, public key on iphone httpS
Secure data transfer : httpS SSL is ‘good enough’ for most of us Get a proper SSL certificate ($30).  Self-signed certs don’t work by default Beware connection time is a little longer for httpS Verify your ssl certificate is installed properlyhttp://www.digicert.com/help/
Verify SSL Cert…
Agenda Connectivity Data format Secure Data transfer UDIDs, Keys, multiple versions, analytics Controlling app from server
What do I send to the server? Think about including UDID (device id) And a Key (compiled within the app) http://example.com/iphone/foo?udid=xxxx&key=yyyy Why?
Unique Device ID (UDID) Each iphone has a unique ID, etched in hardware (just like MAC address) Your app can send UDID with each request Uses metrics on app usage Easy account creation (no signup)
Identify a User (Device) UDID can help you ‘auto –create’ accounts on server Eg. High scores of games Allow users to create a custom user name later Beware of a user using multiple devices (multiple UDIDs)
Metrics A) Client Side metrics Code embedded in your iphone app Users (new, repeat), session length Few companies (Flurry, Pinch Media ..etc) Server side metrics Response time Response size Other
Metrics : Client Side
Server Side Metric : Response Time Log every thing in PARAMS plus more E.g. Want to measure the time spent on each request use around_filter  in Controllerclass MyControlleraround_filter  :log_access,  :only => 			[:get_A]
Response Time … def log_access start_time = Time.now yield end_time = Time.now elapsed = ((end_time - start_time)*1000.0).to_int End
Response Size def log_access start_time = Time.now yield end_time = Time.now elapsed = ((end_time - start_time)*1000.0).to_int response_data_size = response.body.length End
Response Time Chart Time (ms)
Response Size Chart Response size (kbytes)
Access keys Keys are random, ‘sekret’ strings compiled into the iphone app Sample key = “iphone_v1.0_xklajdfoi2” (human readable + ‘hard to guess’) Start using ‘access keys’ from day-1 Each request to server must have a valid key Uses Easy to control client access (Prevent scraping, DOS ..etc) Monitoring (what versions are being used) Support multiple versions, easy upgrade
Access Keys In controller:  @@keys =  [ "iphone_v0.0_foobar” ,                          "iphone_v1.0_afajiu” ,                         "iphone_v2.0_fi98d”,                         "iphone_v2.0_plus_fsafa” ,                        "android_v1.0_fasjlkuo”              		] @@keys_premium = ["iphone_v2.0_plus_fsfa"]
Supporting multiple versions May be supporting 2-3 client versions at a time (users don’t always run the latest) Keep old ‘API’ around, build-out new API		if (is_v2_or_later(key))		{   do something }		else 		{do some thing else} This can get convoluted (see next page…)
Supporting multiple clients…
Supporting Multiple Clients… Have different controllers handle different client versions#define SERVER @”https://foo.com/iphone1”#define SERVER @”https://foo.com/iphone2” Make sure to avoid code duplication Plan-B : End-of-life  If ( !  is_supported_version(key)){send_msg(“please upgrade”);}
Server side : keeping it secure Make sure ‘secret stuff’ doesn’t get logged in log-files In Rails : class Mobile::MobileController < ApplicationControllerfilter_parameter_logging [:key, :uid] 	end Output: Processing IphoneController#get_memberships_and_discounts (for 166.137.132.167 at 2009-07-02 16:07:41) [POST]   Session ID: 126e5a73742f92f85c1158ea63fd960a   Parameters: {"loc"=>"39.282440,-76.765693", "action"=>"get_memberships_and_discounts", "uid"=>”[FILTERED]", "controller"=>"mobile/iphone", "dist"=>"25", "mems"=>"", "key"=>"[FILTERED]"}
Example : Controllers MobileController IPhoneController < MobileController AndroidController < MobileController Most of the shared logic in ‘MobileController’
Example … Class MobileController    @@valid_keys = [……]    def ping to_ret = {}      begin        validate to_ret[:status] = “OK”      rescue to_ret[:error] = $1.message      end       render (:json => to_ret.to_json)    end end
Example … Def validate      #verify the key      if (params[:key].blank?)        raise DiscountsError, "dude, where is my key?"      end      if (params[:uid].blank?)        raise DiscountsError, "dude, who are you?"      end      unless (@@valid_keys .has_key?(params[:key]))        raise DiscountsError, "un supported version, please upgrade"      end       end end
Controlling app behavior from Server
Control … Apps changes are not easy to ‘get out’ Approval process takes time Users may not upgrade to latest version Server changes are under your control and easy to deploy So build in control-switches in the app, that can be directed from server
Control… One example:  Choosing if you are going to show ads? show_ads : {none | admob | tapjoy}
Hosting Shared hosting is fine, but others might swamp your DB, CPU ..etc  If you can, get a VPS (Virtual Private Server) Plans start from $20 / month (SliceHost, Hosting-Rails ..etc) You have full ROOT access to the server (install packages, run CRON jobs ..etc) EC2 is great (for testing, scaling)
Thanks! Sujee Maniyam s@sujee.net http://sujee.net http://DiscountsForMe.net Questions?

More Related Content

Viewers also liked

Viewers also liked (9)

Intranet trends in Finland 2014
Intranet trends in Finland 2014Intranet trends in Finland 2014
Intranet trends in Finland 2014
 
Importancia de un blog en la educación 
Importancia de un blog en la educación Importancia de un blog en la educación 
Importancia de un blog en la educación 
 
Ecolabel affiche generique-a4
Ecolabel affiche generique-a4Ecolabel affiche generique-a4
Ecolabel affiche generique-a4
 
8 herramientas de la web 2.0 para anowhat
8 herramientas de la web 2.0 para anowhat8 herramientas de la web 2.0 para anowhat
8 herramientas de la web 2.0 para anowhat
 
Cwin16 tls-a micro-service deployment - v1.0
Cwin16 tls-a micro-service deployment - v1.0Cwin16 tls-a micro-service deployment - v1.0
Cwin16 tls-a micro-service deployment - v1.0
 
ReLIVE 2008, Closing Keynote - When It's All Over We Still Have to Clear Up
ReLIVE 2008, Closing Keynote  - When It's All Over We Still Have to Clear UpReLIVE 2008, Closing Keynote  - When It's All Over We Still Have to Clear Up
ReLIVE 2008, Closing Keynote - When It's All Over We Still Have to Clear Up
 
9 hplc jntu pharmacy
9 hplc jntu pharmacy9 hplc jntu pharmacy
9 hplc jntu pharmacy
 
Presentation on Presentations
Presentation on PresentationsPresentation on Presentations
Presentation on Presentations
 
Children playing around the world
Children playing around the worldChildren playing around the world
Children playing around the world
 

More from Sujee Maniyam

More from Sujee Maniyam (9)

Reference architecture for Internet of Things
Reference architecture for Internet of ThingsReference architecture for Internet of Things
Reference architecture for Internet of Things
 
Hadoop to spark-v2
Hadoop to spark-v2Hadoop to spark-v2
Hadoop to spark-v2
 
Building secure NoSQL applications nosqlnow_conf_2014
Building secure NoSQL applications nosqlnow_conf_2014Building secure NoSQL applications nosqlnow_conf_2014
Building secure NoSQL applications nosqlnow_conf_2014
 
Hadoop2 new and noteworthy SNIA conf
Hadoop2 new and noteworthy SNIA confHadoop2 new and noteworthy SNIA conf
Hadoop2 new and noteworthy SNIA conf
 
Launching your career in Big Data
Launching your career in Big DataLaunching your career in Big Data
Launching your career in Big Data
 
Hadoop security landscape
Hadoop security landscapeHadoop security landscape
Hadoop security landscape
 
Spark Intro @ analytics big data summit
Spark  Intro @ analytics big data summitSpark  Intro @ analytics big data summit
Spark Intro @ analytics big data summit
 
Cost effective BigData Processing on Amazon EC2
Cost effective BigData Processing on Amazon EC2Cost effective BigData Processing on Amazon EC2
Cost effective BigData Processing on Amazon EC2
 
Iphone client-server app with Rails backend (v3)
Iphone client-server app with Rails backend (v3)Iphone client-server app with Rails backend (v3)
Iphone client-server app with Rails backend (v3)
 

Recently uploaded

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 

Recently uploaded (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 

Lessons from developing an Iphone App + Server backend

  • 1. Lessons from developing anIphone App + Server backend Sujee Maniyam s@sujee.net http://sujee.net http://DiscountsForMe.net Sep 2009
  • 2. Target Audience Iphone app developers Server backend developers for mobile apps Expert level: Beginner - Intermediate
  • 3. My Background Developer (enterprise, web) Java / Php / Ruby First iphone/mobile app
  • 4. App: DiscountsForMe Shows member benefits Based on location V2.0 in app store Memberships: Public radio (KQED, WHYY) Bank of America card AAA, AARP More…
  • 5.
  • 6. Architecture Server (DiscountsForMe.net) serves data Server is Rails app Iphone app talks to the server <Insert usual SERVER ---- INTERNET CLOUD ---- IPHONEpicture here>
  • 7. Connectivity : Simple Start First cut : App made three server calls at startup ping() get_A() get_B() Simulator Iphone over Wi-fi Iphone over 3G LAG-TIME is a problem
  • 8. Connectivity : Minimize Lag Time Noticeable lag time over 3G/Edge Reducing lag time Download in background Condense network calls (especially if the user is waiting for data) So Get_A() Get_B() get_A_and_B()
  • 9. Iphone Connectivity BIG LESSON 1 : Test on IPHONE (not just simulator) Test with WiFi OFF! (3G can be slow to connect, EDGE even worse) You may need to reorganize the logic to improve response time (I had to) LESSON 2 Test in AirPlane Mode (all RADIOS off)(a frequent reason network apps are rejected )
  • 10. Talking to Server : Format Two choices : XML, JSON JSON smaller size than XML (50% less) Json : use TouchJSON library http://code.google.com/p/touchcode/wiki/TouchJSON XML : NSXML(sdk) / TouchXML / KissXMLhttp://www.71squared.co.uk/2009/05/processing-xml-on-the-iphone/ Rails makes it real easy to send Json/xml Some_obj.to_json Some_obj.to_xml
  • 11. Keeping it small Trim objects No need to send all attributes Active records have extra attributes (created_at, updated_at ..etc) Example: my_response = {} my_response[:book_name] = book.name my_response[:book_description] = book.description my_response[:author_name] = book.author.name render(:json => my_response.to_json()) - Compress (zip) response
  • 12. Agenda Connectivity Data format Secure Data transfer UDIDs, Keys, analytics Controlling app from server
  • 13. Secure Data Transfer Plain HTTP is fine most of the time If you want to secure data Symmetric key encryption (shared ‘seckr3t’ key on Iphone app and server) Public-private key encryption (e.g. SSH) : private key on server, public key on iphone httpS
  • 14. Secure data transfer : httpS SSL is ‘good enough’ for most of us Get a proper SSL certificate ($30). Self-signed certs don’t work by default Beware connection time is a little longer for httpS Verify your ssl certificate is installed properlyhttp://www.digicert.com/help/
  • 16. Agenda Connectivity Data format Secure Data transfer UDIDs, Keys, multiple versions, analytics Controlling app from server
  • 17. What do I send to the server? Think about including UDID (device id) And a Key (compiled within the app) http://example.com/iphone/foo?udid=xxxx&key=yyyy Why?
  • 18. Unique Device ID (UDID) Each iphone has a unique ID, etched in hardware (just like MAC address) Your app can send UDID with each request Uses metrics on app usage Easy account creation (no signup)
  • 19. Identify a User (Device) UDID can help you ‘auto –create’ accounts on server Eg. High scores of games Allow users to create a custom user name later Beware of a user using multiple devices (multiple UDIDs)
  • 20. Metrics A) Client Side metrics Code embedded in your iphone app Users (new, repeat), session length Few companies (Flurry, Pinch Media ..etc) Server side metrics Response time Response size Other
  • 22. Server Side Metric : Response Time Log every thing in PARAMS plus more E.g. Want to measure the time spent on each request use around_filter in Controllerclass MyControlleraround_filter :log_access, :only => [:get_A]
  • 23. Response Time … def log_access start_time = Time.now yield end_time = Time.now elapsed = ((end_time - start_time)*1000.0).to_int End
  • 24. Response Size def log_access start_time = Time.now yield end_time = Time.now elapsed = ((end_time - start_time)*1000.0).to_int response_data_size = response.body.length End
  • 25. Response Time Chart Time (ms)
  • 26. Response Size Chart Response size (kbytes)
  • 27. Access keys Keys are random, ‘sekret’ strings compiled into the iphone app Sample key = “iphone_v1.0_xklajdfoi2” (human readable + ‘hard to guess’) Start using ‘access keys’ from day-1 Each request to server must have a valid key Uses Easy to control client access (Prevent scraping, DOS ..etc) Monitoring (what versions are being used) Support multiple versions, easy upgrade
  • 28. Access Keys In controller: @@keys = [ "iphone_v0.0_foobar” , "iphone_v1.0_afajiu” , "iphone_v2.0_fi98d”, "iphone_v2.0_plus_fsafa” , "android_v1.0_fasjlkuo” ] @@keys_premium = ["iphone_v2.0_plus_fsfa"]
  • 29. Supporting multiple versions May be supporting 2-3 client versions at a time (users don’t always run the latest) Keep old ‘API’ around, build-out new API if (is_v2_or_later(key)) { do something } else {do some thing else} This can get convoluted (see next page…)
  • 31. Supporting Multiple Clients… Have different controllers handle different client versions#define SERVER @”https://foo.com/iphone1”#define SERVER @”https://foo.com/iphone2” Make sure to avoid code duplication Plan-B : End-of-life If ( ! is_supported_version(key)){send_msg(“please upgrade”);}
  • 32. Server side : keeping it secure Make sure ‘secret stuff’ doesn’t get logged in log-files In Rails : class Mobile::MobileController < ApplicationControllerfilter_parameter_logging [:key, :uid] end Output: Processing IphoneController#get_memberships_and_discounts (for 166.137.132.167 at 2009-07-02 16:07:41) [POST] Session ID: 126e5a73742f92f85c1158ea63fd960a Parameters: {"loc"=>"39.282440,-76.765693", "action"=>"get_memberships_and_discounts", "uid"=>”[FILTERED]", "controller"=>"mobile/iphone", "dist"=>"25", "mems"=>"", "key"=>"[FILTERED]"}
  • 33. Example : Controllers MobileController IPhoneController < MobileController AndroidController < MobileController Most of the shared logic in ‘MobileController’
  • 34. Example … Class MobileController @@valid_keys = [……] def ping to_ret = {} begin validate to_ret[:status] = “OK” rescue to_ret[:error] = $1.message end render (:json => to_ret.to_json) end end
  • 35. Example … Def validate #verify the key if (params[:key].blank?) raise DiscountsError, "dude, where is my key?" end if (params[:uid].blank?) raise DiscountsError, "dude, who are you?" end unless (@@valid_keys .has_key?(params[:key])) raise DiscountsError, "un supported version, please upgrade" end end end
  • 37. Control … Apps changes are not easy to ‘get out’ Approval process takes time Users may not upgrade to latest version Server changes are under your control and easy to deploy So build in control-switches in the app, that can be directed from server
  • 38. Control… One example: Choosing if you are going to show ads? show_ads : {none | admob | tapjoy}
  • 39. Hosting Shared hosting is fine, but others might swamp your DB, CPU ..etc If you can, get a VPS (Virtual Private Server) Plans start from $20 / month (SliceHost, Hosting-Rails ..etc) You have full ROOT access to the server (install packages, run CRON jobs ..etc) EC2 is great (for testing, scaling)
  • 40. Thanks! Sujee Maniyam s@sujee.net http://sujee.net http://DiscountsForMe.net Questions?